POJ3237 (树链剖分+线段树)
Problem Tree (POJ3237)
题目大意
给定一颗树,有边权。
要求支持三种操作:
操作一:更改某条边的权值。
操作二:将某条路径上的边权取反。
操作三:询问某条路径上的最大权值。
解题分析
树链剖分+线段树。练手题。
参考程序
1 #include <cstdio> 2 #include <cstring> 3 #include <cmath> 4 #include <algorithm> 5 using namespace std; 6 7 #define V 100008 8 #define E 200008 9 #define lson l,m,rt<<1 10 #define rson m+1,r,rt<<1|1 11 #define INF 2000000000 12 13 int cnt,n; 14 int size[V],dep[V],fa[V],son[V],top[V],w[V],rk[V],a[V]; 15 16 struct line{ 17 int u,v,w,nt; 18 }eg[E]; 19 int lt[V],sum; 20 21 void adt(int u,int v,int w){ 22 eg[++sum].u=u; eg[sum].v=v; eg[sum].w=w; eg[sum].nt=lt[u]; lt[u]=sum; 23 } 24 void add(int u,int v,int w){ 25 adt(u,v,w); adt(v,u,w); 26 } 27 28 struct segment_tree{ 29 // 单点修改 区间取反 区间询问 30 int mx[V<<2],mn[V<<2],lazy[V<<2]; 31 void pushup(int rt){ 32 mx[rt]=max(mx[rt<<1],mx[rt<<1|1]); 33 mn[rt]=min(mn[rt<<1],mn[rt<<1|1]); 34 } 35 void pushdown(int rt){ 36 if (lazy[rt]){ 37 lazy[rt<<1]^=1; 38 lazy[rt<<1|1]^=1; 39 int t=mx[rt<<1]; 40 mx[rt<<1]=-mn[rt<<1]; 41 mn[rt<<1]=-t; 42 t=mx[rt<<1|1]; 43 mx[rt<<1|1]=-mn[rt<<1|1]; 44 mn[rt<<1|1]=-t; 45 lazy[rt]=0; 46 } 47 } 48 void build(int l,int r,int rt){ 49 lazy[rt]=0; 50 if (l==r){ 51 mn[rt]=mx[rt]=a[rk[l]]; 52 return; 53 } 54 int m=(l+r)/2; 55 build(lson); 56 build(rson); 57 pushup(rt); 58 } 59 void update_1(int x,int val,int l,int r,int rt){ 60 if (l==r){ 61 mx[rt]=val; 62 mn[rt]=val; 63 return; 64 } 65 pushdown(rt); 66 int m=(l+r)/2; 67 if (x <= m) update_1(x,val,lson); 68 if (m < x) update_1(x,val,rson); 69 pushup(rt); 70 } 71 void update_2(int L,int R,int l,int r,int rt){ 72 if (L<=l && r<=R){ 73 int t=mx[rt]; 74 mx[rt]=-mn[rt]; 75 mn[rt]=-t; 76 lazy[rt]^=1; 77 return; 78 } 79 pushdown(rt); 80 int m=(l+r)/2; 81 if (L <= m) update_2(L,R,lson); 82 if (m < R) update_2(L,R,rson); 83 pushup(rt); 84 } 85 int query(int L,int R,int l,int r,int rt){ 86 if (L<=l && r<=R){ 87 return mx[rt]; 88 } 89 pushdown(rt); 90 int m=(l+r)/2; 91 int res=-INF; 92 if (L <= m) res=max(res,query(L,R,lson)); 93 if (m < R) res=max(res,query(L,R,rson)); 94 return res; 95 } 96 }T; 97 98 void dfs_1(int u){ 99 dep[u]=dep[fa[u]]+1; size[u]=1; son[u]=0; 100 for (int i=lt[u];i;i=eg[i].nt){ 101 int v=eg[i].v; 102 if (v==fa[u]) continue; 103 a[v]=eg[i].w; 104 fa[v]=u; 105 dfs_1(v); 106 size[u]+=size[v]; 107 if (size[v]>size[son[u]]) son[u]=v; 108 } 109 } 110 void dfs_2(int u,int tp){ 111 top[u]=tp; w[u]=++cnt; rk[cnt]=u; 112 if (son[u]) dfs_2(son[u],tp); 113 for (int i=lt[u];i;i=eg[i].nt){ 114 int v=eg[i].v; 115 if (v==fa[u] || v==son[u]) continue; 116 dfs_2(v,v); 117 } 118 } 119 void find_1(int x,int y){ 120 int res=-INF; 121 while (top[x]!=top[y]){ 122 if (dep[top[x]]<dep[top[y]]) swap(x,y); 123 res=max(res,T.query(w[top[x]],w[x],1,n,1)); 124 x=fa[top[x]]; 125 } 126 if (dep[x]>dep[y]) swap(x,y); 127 res=max(res,T.query(w[x]+1,w[y],1,n,1)); 128 printf("%d\n",res); 129 } 130 void find_2(int x,int y){ 131 while (top[x]!=top[y]){ 132 if (dep[top[x]]<dep[top[y]]) swap(x,y); 133 T.update_2(w[top[x]],w[x],1,n,1); 134 x=fa[top[x]]; 135 } 136 if (dep[x]>dep[y]) swap(x,y); 137 T.update_2(w[x]+1,w[y],1,n,1); 138 } 139 140 int main(){ 141 int tt; 142 scanf("%d",&tt); 143 while (tt--){ 144 sum=1; cnt=0; 145 memset(lt,0,sizeof(lt)); 146 scanf("%d",&n); 147 for (int i=1;i<n;i++){ 148 int u,v,w; 149 scanf("%d %d %d",&u,&v,&w); 150 add(u,v,w); 151 } 152 scanf("\n"); 153 dfs_1(1); 154 dfs_2(1,1); 155 T.build(1,n,1); 156 char s[10]; 157 for (scanf("%s",s);strcmp(s,"DONE")!=0;scanf("%s",s)){ 158 int x,y; 159 scanf("%d %d\n",&x,&y); 160 if (strcmp(s,"QUERY")==0){ 161 find_1(x,y); 162 } 163 if (strcmp(s,"CHANGE")==0){ 164 int u=eg[x*2].u , v=eg[x*2].v; 165 if (dep[u]<dep[v]) T.update_1(w[v],y,1,n,1); 166 else T.update_1(w[u],y,1,n,1); 167 } 168 if (strcmp(s,"NEGATE")==0){ 169 find_2(x,y); 170 } 171 } 172 } 173 }