QM 查询对应线段树中部分的最大值
所谓动态开点,就是每个节点用的时候再开,可以去掉许多无用的节点。
总共O(nlogn)级别个节点
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<iostream> #define maxn 200010 #define N 10000100 using namespace std; struct yts { int lch,rch,mx,sum,l,r; }t[N]; int root[maxn],head[maxn],to[maxn],next[maxn],w[maxn],c[maxn],st[maxn]; int fa[20][maxn],dep[maxn],seq[maxn],size[maxn],dd[maxn],e[maxn],rank[maxn]; bool vis[maxn]; char s[5]; int n,m,num,tot,T; void addedge(int x,int y) { num++;to[num]=y;next[num]=st[x];st[x]=num; } void dfs(int x) { e[++tot]=x;size[x]=1; for (int p=st[x];p;p=next[p]) if (to[p]!=fa[0][x]) { fa[0][to[p]]=x; dep[to[p]]=dep[x]+1; dfs(to[p]); size[x]+=size[to[p]]; if (size[to[p]]>size[dd[x]]) dd[x]=to[p]; } } int go_up(int x,int d) { for (int i=17;i>=0;i--) if (d&(1<<i)) x=fa[i][x]; return x; } int LCA(int x,int y) { if (dep[x]>dep[y]) x=go_up(x,dep[x]-dep[y]); else y=go_up(y,dep[y]-dep[x]); if (x==y) return x; for (int i=17;i>=0;i--) if (fa[i][x]!=fa[i][y]) x=fa[i][x],y=fa[i][y]; return fa[0][x]; } void update(int i) { t[i].mx=max(t[t[i].lch].mx,t[t[i].rch].mx); t[i].sum=t[t[i].lch].sum+t[t[i].rch].sum; } void modify(int &i,int l,int r,int x,int d) { if (!i) { i=++tot; t[i].lch=t[i].rch=t[i].mx=t[i].sum=0; t[i].l=l;t[i].r=r; } if (l==r) { t[i].mx=t[i].sum=d; return; } int mid=(t[i].l+t[i].r)/2; if (x<=mid) modify(t[i].lch,l,mid,x,d); if (mid<x) modify(t[i].rch,mid+1,r,x,d); update(i); } int query_mx(int &i,int l,int r) { if (!i) return 0; if (l<=t[i].l && t[i].r<=r) return t[i].mx; int mid=(t[i].l+t[i].r)/2,ans=0; if (l<=mid) ans=max(ans,query_mx(t[i].lch,l,r)); if (mid<r) ans=max(ans,query_mx(t[i].rch,l,r)); return ans; } int query_sum(int &i,int l,int r) { if (!i) return 0; if (l<=t[i].l && t[i].r<=r) return t[i].sum; int mid=(t[i].l+t[i].r)/2,ans=0; if (l<=mid) ans+=query_sum(t[i].lch,l,r); if (mid<r) ans+=query_sum(t[i].rch,l,r); return ans; } int main() { scanf("%d%d",&n,&T); for (int i=1;i<=n;i++) scanf("%d%d",&w[i],&c[i]); for (int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); addedge(x,y);addedge(y,x); } dfs(1); int qwer=0; for (int i=1;i<=n;i++) if (!vis[e[i]]) { int k=e[i]; while (k) { seq[++qwer]=k;head[k]=e[i];vis[k]=1;k=dd[k]; } } tot=0; for (int i=1;i<=n;i++) rank[seq[i]]=i; for (int j=1;j<=17;j++) for (int i=1;i<=n;i++) fa[j][i]=fa[j-1][fa[j-1][i]]; for (int i=1;i<=n;i++) modify(root[c[i]],1,n,rank[i],w[i]); while (T--) { int x,y; scanf("%s%d%d",s,&x,&y); if (s[1]=='C') { modify(root[c[x]],1,n,rank[x],0); c[x]=y; modify(root[c[x]],1,n,rank[x],w[x]); } if (s[1]=='W') { w[x]=y; modify(root[c[x]],1,n,rank[x],w[x]); } if (s[1]=='M') { int z=LCA(x,y),col=c[x],ans=0; while (dep[head[x]]>dep[z]) { ans=max(ans,query_mx(root[col],rank[head[x]],rank[x]));x=fa[0][head[x]]; } ans=max(ans,query_mx(root[col],rank[z],rank[x])); while (dep[head[y]]>dep[z]) { ans=max(ans,query_mx(root[col],rank[head[y]],rank[y]));y=fa[0][head[y]]; } ans=max(ans,query_mx(root[col],rank[z],rank[y])); printf("%d\n",ans); } if (s[1]=='S') { int z=LCA(x,y),col=c[x],ans=0; while (dep[head[x]]>dep[z]) { ans+=query_sum(root[col],rank[head[x]],rank[x]);x=fa[0][head[x]]; } ans+=query_sum(root[col],rank[z],rank[x]); while (dep[head[y]]>dep[z]) { ans+=query_sum(root[col],rank[head[y]],rank[y]);y=fa[0][head[y]]; } ans+=query_sum(root[col],rank[z],rank[y]); ans-=query_sum(root[col],rank[z],rank[z]); printf("%d\n",ans); } } return 0; }