题意:给定一棵树,树上每个点有权值和类型。支持:修改某个点的类型;修改某个点的权值;询问某条链上某个类型的点的和/最大值。点数/类型数/询问数<=100000.
分析:
树链剖分,对每个类型的点建立线段树(动态开点)。
note: 忘记写t_query返回值调半天……
莫名其妙地1A
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 int a[5000005],s[5000005],dep[100005],size[100005],vis[100005],top[100005],wson[100005],fa[100005][20],n,m,t1,t2,t3,t4; 5 int sid[100005],tid[100005],ind,cnt,ch[5000005][2],root[100005],c[100005],w[100005]; 6 vector <int> g[100005]; 7 8 void dfs1(int p){ 9 size[p]=1; 10 vis[p]=1; 11 for(int i=0;i<g[p].size();i++) 12 if(vis[g[p][i]]==0) { 13 dep[g[p][i]]=dep[p]+1; 14 fa[g[p][i]][0]=p; 15 dfs1(g[p][i]); 16 size[p]+=size[g[p][i]]; 17 if(size[g[p][i]]>size[wson[p]]) wson[p]=g[p][i]; 18 } 19 } 20 21 void dfs2(int p){ 22 vis[p]=1; 23 sid[p]=++ind; 24 tid[ind]=p; 25 if(wson[p]) { 26 top[wson[p]]=top[p]; 27 dfs2(wson[p]); 28 } 29 for(int i=0;i<g[p].size();i++) 30 if(vis[g[p][i]]==0) { 31 top[g[p][i]]=g[p][i]; 32 dfs2(g[p][i]); 33 } 34 } 35 36 void lca_presolve() { 37 for(int i=1;i<=17;i++) 38 for(int j=1;j<=n;j++) 39 fa[j][i]=fa[fa[j][i-1]][i-1]; 40 } 41 42 int lca(int p,int q) { 43 if(dep[q]>dep[p]) swap(p,q); 44 for(int i=17;i>=0;i--) if(dep[fa[p][i]]>=dep[q]) p=fa[p][i]; 45 for(int i=17;i>=0;i--) if(fa[p][i]-fa[q][i]) p=fa[p][i],q=fa[q][i]; 46 if(p-q) p=fa[p][0],q=fa[q][0]; 47 return max(p,q); 48 } 49 50 void init() { 51 dep[1]=1; 52 top[1]=1; 53 dfs1(1); 54 memset(vis,0,sizeof vis); 55 dfs2(1); 56 lca_presolve(); 57 } 58 59 void modify(int &p,int l,int r,int pos,int k) { 60 if(p==0) p=++cnt; 61 if(l==r) { 62 a[p]=k; 63 s[p]=k; 64 } 65 else { 66 if(pos<=(l+r)/2) modify(ch[p][0],l,(l+r)/2,pos,k); 67 else modify(ch[p][1],(l+r)/2+1,r,pos,k); 68 a[p]=max(a[ch[p][0]],a[ch[p][1]]); 69 s[p]=s[ch[p][0]]+s[ch[p][1]]; 70 } 71 } 72 73 void tmodify(int t,int pos,int k) { 74 modify(root[t],1,2*n,sid[pos],k); 75 } 76 77 int queryMax(int p,int l,int r,int ql,int qr) { 78 if(p==0) return 0; 79 if(l>qr||r<ql) return 0; 80 if(l>=ql&&r<=qr) return a[p]; 81 return max(queryMax(ch[p][0],l,(l+r)/2,ql,qr),queryMax(ch[p][1],(l+r)/2+1,r,ql,qr)); 82 } 83 84 int querySum(int p,int l,int r,int ql,int qr) { 85 if(p==0) return 0; 86 if(l>qr||r<ql) return 0; 87 if(l>=ql&&r<=qr) return s[p]; 88 return querySum(ch[p][0],l,(l+r)/2,ql,qr)+querySum(ch[p][1],(l+r)/2+1,r,ql,qr); 89 } 90 91 int lqueryMax(int t,int anc,int son) { 92 int ans=0; 93 while(dep[top[son]]>dep[anc]) { 94 ans=max(ans,queryMax(root[t],1,2*n,sid[top[son]],sid[son])); 95 son=fa[top[son]][0]; 96 } 97 ans=max(ans,queryMax(root[t],1,2*n,sid[anc],sid[son])); 98 return ans; 99 } 100 101 int lquerySum(int t,int anc,int son) { 102 int ans=0; 103 while(dep[top[son]]>dep[anc]) { 104 ans+=querySum(root[t],1,2*n,sid[top[son]],sid[son]); 105 son=fa[top[son]][0]; 106 } 107 ans+=querySum(root[t],1,2*n,sid[anc],sid[son]); 108 return ans; 109 } 110 111 int tqueryMax(int t,int p,int q) { 112 int l=lca(p,q); 113 return max(lqueryMax(t,l,p),lqueryMax(t,l,q)); 114 } 115 116 int tquerySum(int t,int p,int q) { 117 int l=lca(p,q); 118 return lquerySum(t,l,p)+lquerySum(t,l,q)-w[l]*(c[l]==c[p]); 119 } 120 121 string str; 122 123 int main(){ 124 ios::sync_with_stdio(false); 125 cin>>n>>m; 126 for(int i=1;i<=n;i++) { 127 cin>>t1>>t2; 128 //tmodify(t2,sid[i],t1); 129 c[i]=t2; 130 w[i]=t1; 131 } 132 for(int i=1;i<n;i++) { 133 cin>>t1>>t2; 134 g[t1].push_back(t2); 135 g[t2].push_back(t1); 136 } 137 init(); 138 for(int i=1;i<=n;i++) { 139 tmodify(c[i],i,w[i]); 140 } 141 for(int i=1;i<=m;i++) { 142 cin>>str>>t1>>t2; 143 if(str=="CC") { 144 tmodify(c[t1],t1,0); 145 tmodify(t2,t1,w[t1]); 146 c[t1]=t2; 147 } 148 if(str=="CW") { 149 tmodify(c[t1],t1,0); 150 tmodify(c[t1],t1,t2); 151 w[t1]=t2; 152 } 153 if(str=="QS") { 154 cout<<tquerySum(c[t1],t1,t2)<<endl; 155 } 156 if(str=="QM") { 157 cout<<tqueryMax(c[t1],t1,t2)<<endl; 158 } 159 } 160 }