poj3237 Tree
树链剖分基本操作:
1. 修改第i条边的权值。
2. 对树上一条路径的权值取反(正变负,负变正)。
3. 查询树上一条路径的权值的最大值。
因为要取反,所以要同时维护最大值和最小值。
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define lson l,mid,rt<<1 5 #define rson mid+1,r,rt<<1|1 6 using namespace std; 7 8 const int N=1e4+10; 9 const int M=2e4+10; 10 const int inf=0x3f3f3f3f; 11 12 int head[N],to[M],nxt[M],w[M],kk[M];//kk:边的编号 13 int tot; 14 int dep[N],fa[N],siz[N],son[N],idx[N];//idx:每个点与它的父亲之间的边的编号 15 int top[N],id[N],wt[N]; 16 int cnt; 17 int mx[N<<2],mi[N<<2],tag[N<<2]; 18 int num[N];//第x条边(按输入顺序)的新编号 19 int n; 20 21 inline void add(int u,int v,int x,int i){ 22 to[++tot]=v,nxt[tot]=head[u],w[tot]=x,kk[tot]=i,head[u]=tot; 23 } 24 25 void dfs1(int u,int f){ 26 dep[u]=dep[f]+1; 27 fa[u]=f; 28 siz[u]=1; 29 int maxs=-1; 30 for(int i=head[u];i;i=nxt[i]){ 31 int v=to[i]; 32 if(v==f) continue; 33 dfs1(v,u); 34 siz[u]+=siz[v]; 35 idx[v]=i; 36 if(siz[v]>maxs) maxs=siz[v],son[u]=v; 37 } 38 } 39 40 void dfs2(int u,int topf){ 41 id[u]=++cnt; 42 wt[cnt]=w[idx[u]]; 43 top[u]=topf; 44 num[kk[idx[u]]]=cnt; 45 if(!son[u]) return; 46 dfs2(son[u],topf); 47 for(int i=head[u];i;i=nxt[i]){ 48 int v=to[i]; 49 if(v==fa[u]||v==son[u]) continue; 50 dfs2(v,v); 51 } 52 } 53 54 inline void push_up(int rt){ 55 mx[rt]=max(mx[rt<<1],mx[rt<<1|1]); 56 mi[rt]=min(mi[rt<<1],mi[rt<<1|1]); 57 } 58 59 inline void push_down(int rt){ 60 if(tag[rt]){ 61 int tmp=mx[rt<<1]; 62 mx[rt<<1]=-mi[rt<<1]; 63 mi[rt<<1]=-tmp; 64 tmp=mx[rt<<1|1]; 65 mx[rt<<1|1]=-mi[rt<<1|1]; 66 mi[rt<<1|1]=-tmp; 67 tag[rt<<1]^=1; tag[rt<<1|1]^=1; 68 tag[rt]=0; 69 } 70 } 71 72 void build(int l,int r,int rt){ 73 tag[rt]=0; 74 if(l==r){ 75 mx[rt]=mi[rt]=wt[l]; 76 return; 77 } 78 int mid=(l+r)>>1; 79 build(lson),build(rson); 80 push_up(rt); 81 } 82 83 void update1(int x,int z,int l,int r,int rt){ 84 if(l==r){ 85 mx[rt]=mi[rt]=z; 86 return; 87 } 88 push_down(rt); 89 int mid=(l+r)>>1; 90 if(x<=mid) update1(x,z,lson); 91 if(x>mid) update1(x,z,rson); 92 push_up(rt); 93 } 94 95 void update2(int x,int y,int l,int r,int rt){ 96 if(x<=l&&y>=r){ 97 int tmp=mx[rt]; 98 mx[rt]=-mi[rt]; 99 mi[rt]=-tmp; 100 tag[rt]^=1; 101 return; 102 } 103 push_down(rt); 104 int mid=(l+r)>>1; 105 if(x<=mid) update2(x,y,lson); 106 if(y>mid) update2(x,y,rson); 107 push_up(rt); 108 } 109 110 int query(int x,int y,int l,int r,int rt){ 111 if(x<=l&&y>=r) return mx[rt]; 112 push_down(rt); 113 int ans=-inf; 114 int mid=(l+r)>>1; 115 if(x<=mid) ans=max(ans,query(x,y,lson)); 116 if(y>mid) ans=max(ans,query(x,y,rson)); 117 return ans; 118 } 119 120 inline void uprange1(int x,int z){ 121 update1(num[x],z,1,n,1); 122 } 123 124 void uprange2(int x,int y){ 125 while(top[x]!=top[y]){ 126 if(dep[top[x]]<dep[top[y]]) swap(x,y); 127 update2(id[top[x]],id[x],1,n,1); 128 x=fa[top[x]]; 129 } 130 if(x==y) return; 131 if(dep[x]>dep[y]) swap(x,y); 132 update2(id[x]+1,id[y],1,n,1); 133 } 134 135 int qrange(int x,int y){ 136 int ans=-inf; 137 while(top[x]!=top[y]){ 138 if(dep[top[x]]<dep[top[y]]) swap(x,y); 139 ans=max(ans,query(id[top[x]],id[x],1,n,1)); 140 x=fa[top[x]]; 141 } 142 if(x==y) return ans; 143 if(dep[x]>dep[y]) swap(x,y); 144 return max(ans,query(id[x]+1,id[y],1,n,1)); 145 } 146 147 void init(){ 148 tot=cnt=0; 149 memset(head,0,sizeof(head)); 150 memset(son,0,sizeof(son)); 151 } 152 153 int main() 154 { 155 int T; 156 char ch[10]; 157 scanf("%d",&T); 158 while(T--){ 159 init(); 160 scanf("%d",&n); 161 for(int i=1;i<n;i++){ 162 int u,v,x; 163 scanf("%d%d%d",&u,&v,&x); 164 add(u,v,x,i); 165 add(v,u,x,i); 166 } 167 dfs1(1,0); dfs2(1,1); 168 build(1,n,1); 169 while(~scanf("%s",ch)){ 170 if(ch[0]=='D') break; 171 if(ch[0]=='C'){ 172 int x,z; 173 scanf("%d%d",&x,&z); 174 uprange1(x,z); 175 } 176 else if(ch[0]=='N'){ 177 int x,y; 178 scanf("%d%d",&x,&y); 179 uprange2(x,y); 180 } 181 else{ 182 int x,y; 183 scanf("%d%d",&x,&y); 184 printf("%d\n",qrange(x,y)); 185 } 186 } 187 } 188 return 0; 189 }