hdu5221 树上区间修改求所有和:树链剖分
需要注意两个地方:
1.修改整棵子树就是节点的size,因为子树映射到线段树上是连续的
2.并不是区间修改成一个值,所以预处理出子树的和,然后ok数组判断是否被占领
1 #pragma comment(linker,"/STACK:1024000000,1024000000") 2 #include<stdio.h> 3 #include<string.h> 4 #include<algorithm> 5 #define maxn 200005 6 #define maxm 800005 7 using namespace std; 8 9 int Now,Head[maxm],Next[maxm],Point[maxm]; 10 int num[maxn],father[maxn],deep[maxn],son[maxn]; 11 int top[maxn],tree[maxn],pre[maxn],cnt; 12 int n,a[maxn],sumv[maxm],ok[maxm],ansv[maxm]; 13 14 void add(int x,int y) 15 { 16 Next[++Now]=Head[x]; 17 Head[x]=Now; 18 Point[Now]=y; 19 } 20 //树链剖分 21 void dfs1(int u) 22 { 23 num[u]=1; 24 for (int i=Head[u];i!=-1;i=Next[i]) 25 { 26 int v=Point[i]; 27 if (v==father[u]) continue; 28 father[v]=u; 29 deep[v]=deep[u]+1; 30 dfs1(v); 31 num[u]+=num[v]; 32 if (son[u]==-1||num[v]>num[son[u]]) son[u]=v; 33 } 34 } 35 void dfs2(int u,int lead) 36 { 37 top[u]=lead; 38 tree[u]=++cnt; 39 pre[cnt]=u; 40 if (son[u]==-1) return; 41 dfs2(son[u],lead); 42 for (int i=Head[u];i!=-1;i=Next[i]) 43 { 44 int v=Point[i]; 45 if (father[u]!=v&&son[u]!=v) dfs2(v,v); 46 } 47 } 48 //线段树 49 void build(int o,int l,int r) 50 { 51 sumv[o]=0; 52 if (l==r) 53 { 54 sumv[o]=a[pre[l]]; 55 return; 56 } 57 int mid=l+(r-l)/2; 58 build(o*2,l,mid); 59 build(o*2+1,mid+1,r); 60 sumv[o]=sumv[o*2]+sumv[o*2+1]; 61 } 62 void pushdown(int o) 63 { 64 if (ok[o]) 65 { 66 ok[o*2]=ok[o*2+1]=1; 67 ansv[o*2]=sumv[o*2]; 68 ansv[o*2+1]=sumv[o*2+1]; 69 ok[o]=ansv[o]=0; 70 } 71 } 72 void pushup(int o) 73 { 74 ansv[o]=ansv[o*2]+ansv[o*2+1]; 75 ok[o]=ok[o*2]&ok[o*2+1]; 76 } 77 void update(int o,int l,int r,int ql,int qr,int d) 78 { 79 if (ql<=l&&r<=qr) 80 { 81 ok[o]=d; 82 if (ok[o]) ansv[o]=sumv[o]; 83 else ansv[o]=0; 84 return; 85 } 86 pushdown(o); 87 int mid=l+(r-l)/2; 88 if (ql<=mid) update(o*2,l,mid,ql,qr,d); 89 if (qr>mid) update(o*2+1,mid+1,r,ql,qr,d); 90 pushup(o); 91 } 92 //更改操作 93 void change1(int l,int r) 94 { 95 while (top[l]!=top[r]) 96 { 97 if (deep[top[l]]<deep[top[r]]) swap(l,r); 98 update(1,1,n,tree[top[l]],tree[l],1); 99 l=father[top[l]]; 100 } 101 if (deep[l]>deep[r]) swap(l,r); 102 update(1,1,n,tree[l],tree[r],1); 103 } 104 void change2(int o) 105 { 106 update(1,1,n,tree[o],tree[o],0); 107 } 108 void change3(int o) 109 { 110 update(1,1,n,tree[o],tree[o]+num[o]-1,1); 111 } 112 113 int main() 114 { 115 int T,i,x,y,q,l,r,k; 116 scanf("%d",&T); 117 while (T--) 118 { 119 scanf("%d",&n); 120 Now=0; cnt=0; 121 deep[1]=1; father[1]=0; 122 memset(son,-1,sizeof(son)); 123 memset(Head,-1,sizeof(Head)); 124 for (i=1;i<=n;i++) scanf("%d",&a[i]); 125 for (i=1;i<n;i++) 126 { 127 scanf("%d%d",&x,&y); 128 add(x,y); add(y,x); 129 } 130 dfs1(1); dfs2(1,1); 131 memset(ansv,0,sizeof(ansv)); 132 memset(ok,0,sizeof(ok)); 133 build(1,1,n); 134 scanf("%d",&q); 135 while (q--) 136 { 137 scanf("%d",&k); 138 if (k==1) 139 { 140 scanf("%d%d",&l,&r); 141 change1(l,r); 142 } 143 else if (k==2) 144 { 145 scanf("%d",&l); 146 change2(l); 147 } 148 else 149 { 150 scanf("%d",&l); 151 change3(l); 152 } 153 printf("%d\n",ansv[1]); 154 } 155 } 156 return 0; 157 }