文章标题
来源:互联网 发布:淘宝网的商品分类 编辑:程序博客网 时间:2024/06/05 18:05
给定一棵N 个节点的树,标号从1~N。每个点有一个权值。要求维护两种操作:
C i x(0<=x<2^31) 表示将i 点权值变为x
Q i j x(0<=x<2^31) 表示询问i 到j 的路径上有多少个值为x 的节点
N <= 100000
显然要用链剖, 然而直接做貌似不行,由于询问的权值只涉及到与那个权值相关的点与操作,考虑每个权值独立做,对于操作1,可以看做是在原权值上删点,新权值加点。
一个权值做完做下一个权值时,线段树可以打个clear标记表示清0 。
独立做这个想法可真是棒啊。
#include<cstdio>#include<cstring>#include<algorithm>#include<vector>using namespace std ;#define N 200010#define psb( x ) push_back( x ) int i , j , k , Q , n , g[N] , T ; struct edge { int y , l ; }f[N*2] ;void Ins( int x , int y ) { f[++T].y = y , f[T].l = g[x] , g[x] = T ; f[++T].y = x , f[T].l = g[y] , g[y] = T ;}int w[N] ;struct stream { int x , y , va ; int id ;}z[ N * 3 ] ;char s[2] ;bool cmp( stream a , stream b ) { return a.va < b.va ;}bool _cmp( stream a , stream b ) { return a.id < b.id ;}int tmp[N*3] ;struct Operation { int typ , x , y , ori ; // typ : 1 delete // 2 Insert // 3 Query};vector< Operation > seq[ N * 3 ] ;int l[32][N] , de[N] , fa[N] , tid[N] , top[N] , siz[N] , son[N] , dfn , inx[32] ;void Find_Edge( int po ) { int ax = 0 ; siz[po] = 1 ; l[0][po] = fa[po] ; for( i=1 ; i<=30 && de[po] >= inx[i] ; i++ ) l[i][po] = l[i-1][ l[i-1][po] ] ; for( int k = g[po] ; k ; k = f[k].l ) if( fa[po]!=f[k].y ) { de[ f[k].y ] = de[po] + 1 ; fa[ f[k].y ] = po ; Find_Edge( f[k].y ) ; if( siz[ f[k].y ] > ax ) { ax = siz[ f[k].y ] ; son[po] = f[k].y ; } siz[po] += siz[ f[k].y ] ; }}void Mark_Edge( int po , int anc ) { tid[po] = ++ dfn ; top[po] = anc ; if( son[po] != 0 ) Mark_Edge( son[po] , anc ) ; for( int k = g[po] ; k ; k=f[k].l ) if( f[k].y != fa[po] && f[k].y != son[po] ) { Mark_Edge( f[k].y , f[k].y ) ; }}int LCA( int x , int y ) { if( de[x] > de[y] ) swap( x , y ) ; for( int sub = de[y] - de[x] , j = 0 ; sub ; sub /= 2 , j++ ) if( sub % 2 ) y = l[j][y] ; if( y==x ) return x ; for( int i = 1 ; i>=0 ; ) { for( i=30 ; i>=0 ; i-- ) if( l[i][x]!=l[i][y] ) { x = l[i][x] , y = l[i][y] ; break ; } } return fa[x] ;}int sum[N*4] ;int ans[N] ;bool clr[N*4] ;void Effect( int l , int r , int p ) { if( clr[p] ) { sum[p] = 0 ; if( l!=r ) clr[p*2] = clr[p*2+1] = 1 ; } clr[p] = 0 ;}void Clear( int po ) { clr[po] = 1 ; Effect( 1 , n , po ) ;}void Insert( int l , int r , int tar , int delta , int p ) { int m = ( l + r ) / 2 ; Effect( l , r , p ) ; if( l==r ) { sum[p] += delta ; return ; } if( tar <= m ) Insert( l , m , tar , delta , p*2 ) ; else Insert( m+1 , r , tar , delta , p*2+1 ) ; Effect( l , m , p * 2 ) , Effect( m+1 , r , p * 2 + 1 ) ; sum[p] = sum[p*2] + sum[p*2+1] ;}int Ask( int l , int r , int _l , int _r , int p ) { int m = ( l+r ) / 2 ; Effect( l , r , p ) ; if( _l==l && _r==r ) return sum[p] ; if( _r<=m ) return Ask( l , m , _l , _r , p*2 ) ; else if( _l>m ) return Ask( m+1 , r , _l , _r , p*2+1 ) ; else return Ask( l , m , _l , m , p*2 ) + Ask( m+1 , r , m+1 , _r , p*2+1 ) ;}int Chain_Process( int u , int v ) { int lca = LCA( u , v ) ; int k = 2 , ret = 0 ; while( k-- ) { while( top[u]!=top[lca] ) { ret += Ask( 1 , n , tid[ top[u] ] , tid[u] , 1 ) ; u = fa[ top[u] ] ; } ret += Ask( 1 , n , tid[ lca ] , tid[u] , 1 ) ; swap( u , v ) ; } ret -= Ask( 1 , n , tid[ lca ] , tid[ lca ] , 1 ) ; return ret ;}int main() {freopen("k.in","r",stdin ) ;freopen( "k.out","w",stdout ) ; for( i=1,inx[0] = 1 ; i<=31 ; i++ ) inx[i] = inx[i-1] * 2 ; scanf("%d%d",&n,&Q ) ; for( i=1 ; i<=n ; i++ ) scanf("%d",&w[i] ) ; for( i=2 ; i<=n ; i++ ) { int x , y ; scanf("%d%d" , &x,&y ) ; Ins( x ,y ) ; } for( i=1 ; i<=Q ; i++ ) { scanf("%s",s ) ; z[i].id = i ; if( s[0] == 'Q' ) { scanf("%d%d%d",&z[i].x , &z[i].y , &z[i].va ) ; } else { scanf("%d%d",&z[i].x,&z[i].va ) ; } } for( i=1 ; i<=n ; i++ ) { z[++Q].x = i , z[Q].va = w[i] ; z[Q].id = -1 ; z[Q].y = i ; } sort( z+1 , z+1+Q , cmp ) ; int disva = 0 ; for( i=1 ; i<=Q ; i++ ) { if( z[i].va != z[i-1].va ) ++disva ; tmp[i] = disva ; } for( i=1 ; i<=Q ; i++ ) z[i].va = tmp[i] ; sort( z+1 , z+1+Q , _cmp ) ; i = 1 ; while( z[i].id == -1 ) { Operation P ; P.typ = 2 ; P.x = z[i].x ; seq[ z[i].va ].psb( P ) ; w[ z[i].y ] = z[i].va ; i++ ; } for( ; i<=Q ; i++ ) { Operation P ; if( z[i].y ) { P.x = z[i].x , P.y = z[i].y , P.typ = 3 , P.ori = z[i].id ; seq[ z[i].va ].psb( P ) ; } else { P.x = z[i].x , P.typ = 1 ; seq[ w[ z[i].x ] ].psb( P ) ; P.typ = 2 ; w[ z[i].x ] = z[i].va ; seq[ z[i].va ].psb( P ) ; } } Find_Edge( 1 ) ; Mark_Edge( 1,1 ) ; memset( ans , 255 , sizeof ans ) ; int cnt = 0 ; for( i=1 ; i<=disva ; i++ ) { Clear( 1 ) ; for( vector< Operation >::iterator it = seq[i].begin() ; it != seq[i].end() ; it++ ) { if( it->typ== 1 ) { Insert( 1 , n , tid[ it->x ] , -1 , 1 ) ; } else if( it->typ==2 ) { Insert( 1 , n , tid[ it->x ] , 1 , 1 ) ; cnt ++ ; } else { ans[ it->ori ] = Chain_Process( it->x , it->y ) ; } } } for( i=1 ; i<=Q ; i++ ) if( ans[i] != -1 ) printf("%d\n",ans[i] ) ; } // typ : 1 delete // 2 Insert // 3 Query
0 0
- 文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题 文章标题 文章标题 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- 文章标题
- apache .htaccess 实现在URL后面自动加 / 利SEO操作
- tcp/ip协议
- SSH中异步验证用户名是否已存在
- 1081. Rational Sum (20)
- php学习-10while循环
- 文章标题
- php学习-11for循环
- Codeforces Round #316 (Div. 2) (ABC题)
- codeforces 232D. Fence
- 黑马程序员 继承
- 【笔记】互联网+:运营商
- mysql主从同步报错 Got fatal error 1236 from master when reading data from binary log
- php学习-12函数
- tar压缩命令