8.4 POJ 3237 (树链剖分+线段树
题意:边权树链剖分 ,三种操作
1.CHANGE把第i条边的权值改为a
2.NEGATE把第a个点到第b个点的边的权值全部取相反数
3.QUERY求第a个点到第b个点的最大边权。
分析:
这次是没看板子自己默的树链剖分哈哈
意料之中的出现了错误:
1.链式前向星用的不熟,之前都是vector存边的 ,但poj上的树链剖分题好像vectoc会超时
2.取反的lazy标记更新要考虑负负得正
这种复杂一点的线段树用struct存就写的比较清楚,比数组好一些
//树链剖分 b #include<cstdio> #include<iostream> #include<algorithm> #include<cstring> #define fi first #define se second #define rep( i ,x ,y ) for( int i= x; i<= y ;i++ ) #define reb( i ,y ,x ) for( int i= y; i>= x ;i-- ) #define mem( a ,x ) memset( a ,x ,sizeof(a)) #define li i<<1 #define ri i<<1|1 using namespace std; typedef long long ll; typedef long double ld; typedef pair<int ,int> pii; typedef pair<ll ,ll> pll; typedef pair<string ,int> psi; const int inf = 0x3f3f3f3f; const int N = 100005; const int M = 1000005; struct Tree{ int i ,l ,r; int mn ,mx ,lazy; } tr[N<<2]; struct E{ int u ,v ,c; }e[N]; struct Edge{ int to ,next; }edge[N<<1]; int val[N] ,head[N<<1]; int fa[N] ,son[N] ,sz[N] ,top[N] ,dfn[N] ,rnk[N] ,dep[N]; int n ,q ,tot=0 ,cnt = 0; // segment tree inline void addedge(int u ,int v){ edge[++cnt].to = v; edge[cnt].next = head[u]; head[u] = cnt; //cout<<u<<" "<<v<<" cnt "<<cnt<<endl; } inline void neg( int i ){ tr[i].mx *=-1; tr[i].mn *=-1; swap( tr[i].mx ,tr[i].mn); } inline void push_up( int i ){ tr[i].mx = max( tr[li].mx ,tr[ri].mx ); tr[i].mn = min( tr[li].mn ,tr[ri].mn ); } inline void push_down( int i ){ if( !tr[i].lazy )return; tr[i].lazy = 0; // lazy取反 负负得正 tr[li].lazy ^= 1 ; tr[ ri].lazy ^= 1; neg(li); neg(ri); return; } void build( int i ,int L ,int R ){ tr[i].l = L; tr[i].r = R; tr[i].lazy = 0; if( L== R ){ tr[i].mn = tr[i].mx = val[ rnk[L] ]; return; } int m = (tr[i].l+tr[i].r)>>1; build( li ,L ,m ); build( ri ,m+1 ,R); push_up( i ); } void negat( int i ,int L ,int R){ if( tr[i].l == tr[i].r ){ neg( i ); return; } push_down(i); if( L <= tr[i].l && tr[i].r <= R ){ tr[i].lazy = 1; neg( i ); return; } int m = (tr[i].l+tr[i].r)>>1; if( L <= m )negat( li ,L ,R ); if( R > m )negat( ri ,L ,R ); push_up(i); return; } void updata( int i ,int p ,int k ){ if( tr[i].l ==p && tr[i].r==p ){ tr[i].mn = tr[i].mx = k; return; } push_down(i); int m = (tr[i].l+tr[i].r)>>1; if( p <= m )updata( li ,p ,k ); if( p > m )updata( ri ,p ,k ); push_up(i); return; } int query(int i ,int L, int R ){ //cout<<"q l ,r "<<tr[i].l<<" "<<tr[i].r<<" L ,R "<<L << " " <<R <<" " <<rnk[L] <<" "<<rnk[R]<<endl; if( tr[i].l == tr[i].r ){ return tr[i].mx; } push_down(i); int mx = -inf; if( L <= tr[i].l && tr[i].r <= R ){ return tr[i].mx; } int m = (tr[i].l+tr[i].r)>>1; if( L <= m )mx =max( mx ,query(li ,L ,R ) ); if( R > m )mx =max( mx ,query(ri ,L ,R ) ); return mx; } // c_tree void init( ){ tot = cnt = 0; mem( head ,0 ); mem( son ,0 ); } void dfs1( int u ,int f ,int d ){ sz[u] = 1; fa[u] = f; dep[u] = d; for( int i= head[u] ; i ;i = edge[i].next ){ int v = edge[i] .to; if( v==f )continue; dfs1( v ,u ,d+1 ); sz[u] += sz[v]; if( sz[ son[u] ] < sz[v] )son[u] = v; } } void dfs2( int u ,int tp ){ top[u] = tp; dfn[u] = ++ tot; rnk[tot] = u; if( son[u] )dfs2( son[u] ,tp ); for( int i =head[u] ;i ;i = edge[i].next ){ int v = edge[i].to; if( v!= fa[u] && v!=son[u] )dfs2(v ,v); } } void c_negate( int x ,int y ){ int fx = top[x] ,fy = top[y]; while( fx!=fy ){ if( dep[fx] < dep[fy] ){ swap( x ,y ); swap(fx ,fy); } negat( 1 ,dfn[fx] ,dfn[x] ); x= fa[fx]; fx = top[x]; } if( x==y )return; if( dfn[x] > dfn[y] )swap(x ,y); negat( 1 ,dfn[son[x]] ,dfn[y] ); } int c_query(int x ,int y ){ int mx = -inf; int fx = top[x] ,fy = top[y]; //cout<<x<< " " <<y<<" " <<fx <<" "<<fy<<endl; while( fx!=fy ){ if( dep[fx] < dep[fy] ){ swap( x ,y ); swap(fx ,fy); } mx = max(mx ,query( 1 ,dfn[fx] ,dfn[x] ) ); x= fa[fx]; fx = top[x]; } if( x==y )return mx; if( dfn[x] > dfn[y] )swap(x ,y); mx = max(mx ,query( 1 ,dfn[son[x]] ,dfn[y] ) ); return mx; } void rev_val( ){ rep( i ,1 ,n-1 ){ int u =e[i].u ,v = e[i].v; if( dep[v] > dep[u] )swap( e[i].u ,e[i].v ); val[ e[i].u ] = e[i].c; } } int T; int main( ){ //freopen( "out.txt" ,"w" ,stdout ); scanf( "%d" ,&T ); while( T-- ){ init( ); scanf("%d" ,&n); rep( i ,1 ,n-1 ){ scanf("%d%d%d" ,&e[i].u ,&e[i].v ,&e[i].c); addedge( e[i].u ,e[i].v ); addedge( e[i].v ,e[i].u ); } dfs1( 1 ,0 ,1 ); dfs2( 1 ,1 ); rev_val( ); build( 1 ,1 ,n ); char op[15] ; int a ,b ,v; while( true ){ cin >>op; if(op[0]=='D')break; if(op[0]=='C'){ scanf("%d%d" ,&a ,&v ); updata( 1 ,dfn[ e[a].u ] ,v ); } if( op[0]=='Q' ){ scanf("%d%d" ,&a ,&b ); printf("%d\n" ,c_query(a ,b)); } if( op[0]=='N' ){ scanf("%d%d" ,&a ,&b ); c_negate( a, b ); } } } return 0; }