一眼树剖题
对每种颜色开一颗线段树,动态开点,记录最大值与和,查询直接查找,修改的话只会修改单点,所以最多增加2logn个节点
(原来把题目看错了,以为修改也是修改连续一段的,似乎这样空间会大很多)
#include <vector> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int Maxn = 1000005; int sum[Maxn*10], maxx[Maxn*10]; int Fa[Maxn], fa[Maxn]; int dep[Maxn], T[Maxn]; int size[Maxn], dfn[Maxn]; int L[Maxn], R[Maxn]; int w[Maxn], c[Maxn]; int son[Maxn*10][2]; int n,Q,x,y,id,tim; char S[10]; vector <int> e[Maxn]; void find_heavy_edge(int x){ dep[x] = dep[fa[x]]+1; int len = e[x].size(); size[x] = 1; for (int i=0;i<len;i++) if (e[x][i]!=fa[x]){ fa[e[x][i]] = x; find_heavy_edge(e[x][i]); size[x] += size[e[x][i]]; } } bool cmp(const int &a,const int &b) { return size[a] > size[b]; } void link_heavy_edge(int x){ dfn[++tim] = x; L[x] = tim; sort(e[x].begin(),e[x].end(),cmp); if (x>1) e[x].erase( e[x].begin() ); else Fa[x] = x; int len = e[x].size(); for (int i=0;i<len;i++) { if (i==0) Fa[e[x][i]] = Fa[x]; else Fa[e[x][i]] = e[x][i]; link_heavy_edge(e[x][i]); } R[x] = tim; } void insert(int &p,int l,int r,int pos,int data){ if (p==0) p = ++id; if (l==r){ sum[p] = maxx[p] = data; return; } int mid = (l+r)>>1; if (mid>=pos) insert(son[p][0],l,mid,pos,data); else insert(son[p][1],mid+1,r,pos,data); sum[p] = sum[son[p][0]] + sum[son[p][1]]; maxx[p] = max( maxx[son[p][0]], maxx[son[p][1]] ); } int query_sum(int p,int l,int r,int L,int R){ if (p==0) return 0; if (L>r || l>R) return 0; if (L<=l && R>=r) return sum[p]; int mid = (l+r)>>1; return query_sum(son[p][0],l,mid,L,R) + query_sum(son[p][1],mid+1,r,L,R); } int query_max(int p,int l,int r,int L,int R){ if (p==0) return 0; if (L>r || l>R) return 0; if (L<=l && R>=r) return maxx[p]; int mid = (l+r)>>1; return max( query_max(son[p][0],l,mid,L,R), query_max(son[p][1],mid+1,r,L,R) ); } void work1(){ insert(T[c[x]],1,n,L[x],0); c[x] = y; insert(T[c[x]],1,n,L[x],w[x]); } void work2(){ w[x] = y; insert(T[c[x]],1,n,L[x],w[x]); } void work3(){ int col = c[x], ans = 0; while (Fa[x]!=Fa[y]) { if (dep[Fa[x]]<dep[Fa[y]]) swap(x,y); ans += query_sum(T[col],1,n,L[Fa[x]],L[x]); x = fa[Fa[x]]; } if (L[x]>L[y]) swap(x,y); ans += query_sum(T[col],1,n,L[x],L[y]); printf("%d\n",ans); } void work4(){ int col = c[x], ans = 0; while (Fa[x]!=Fa[y]) { if (dep[Fa[x]]<dep[Fa[y]]) swap(x,y); ans = max(ans, query_max(T[col],1,n,L[Fa[x]],L[x]) ); x = fa[Fa[x]]; } if (L[x]>L[y]) swap(x,y); ans = max(ans, query_max(T[col],1,n,L[x],L[y]) ); printf("%d\n",ans); } int main(){ scanf("%d%d",&n,&Q); for (int i=1;i<=n;i++) scanf("%d%d",&w[i],&c[i]); for (int i=1;i<n;i++){ scanf("%d%d",&x,&y); e[x].push_back(y); e[y].push_back(x); } find_heavy_edge(1); link_heavy_edge(1); for (int i=1;i<=n;i++) insert(T[c[i]],1,n,L[i],w[i]); while (Q--){ scanf("%s%d%d",S,&x,&y); if (S[0]=='C' && S[1]=='C') work1(); if (S[0]=='C' && S[1]=='W') work2(); if (S[0]=='Q' && S[1]=='S') work3(); if (S[0]=='Q' && S[1]=='M') work4(); } return 0; }