BZOJ 3531: [Sdoi2014]旅行
阿新 • • 發佈:2018-12-21
這題就是樹鏈剖分,對於多種宗教就開多個線段樹,動態開點就好了。
記得卡記憶體
然而一個城市的宗教變了之後還能在變回來,導致我調了一下午。。。
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<queue> #define qmin(x,y) (x=min(x,y)) #define qmax(x,y) (x=max(x,y)) using namespace std; typedef long long ll; const int Maxn=410000; const int Maxm=4100000; int to[Maxn],nxt[Maxn],first[Maxn],tot=1; int dep[Maxn],fa[Maxn],son[Maxn],top[Maxn],ran[Maxn]; int n,q,u,v,cnt,rot[Maxn],a[Maxn],b[Maxn],topp; int tl[Maxm],tr[Maxm],tn[Maxm],tm[Maxm],ls[Maxm],rs[Maxm]; char getch() { char ch=getchar(); while(ch!='Q'&&ch!='C'&&ch!='S'&&ch!='M'&&ch!='W') ch=getchar(); return ch; } inline void add(int u,int v) { to[tot]=v; nxt[tot]=first[u]; first[u]=tot++; to[tot]=u; nxt[tot]=first[v]; first[v]=tot++; } int dfs1(int root) { int siz=1,sizm=0; for(int i=first[root];i;i=nxt[i]) if(!dep[to[i]]) { dep[to[i]]=dep[root]+1;fa[to[i]]=root; int temp=dfs1(to[i]); siz+=temp; if(sizm<=temp) son[root]=to[i],sizm=temp; } return siz; } void dfs2(int root,int topp) { top[root]=topp; ran[root]=++cnt; if(son[root]) dfs2(son[root],topp); for(int i=first[root];i;i=nxt[i]) if(!ran[to[i]]) dfs2(to[i],to[i]); } int newnode(int l,int r,int x=0) { int root=++topp; tl[root]=l;tr[root]=r; tn[root]=tm[root]=x; return root; } void update(int root) { tn[root]=tn[ls[root]]+tn[rs[root]]; tm[root]=max(tm[ls[root]],tm[rs[root]]); } void add(int root,int x,int y) { int l=tl[root],r=tr[root],mid=(l+r)>>1; if(l==r) { tn[root]=tm[root]=y; return; } if(x<=mid) { if(!ls[root]) ls[root]=newnode(l,mid,y); add(ls[root],x,y); } else { if(!rs[root]) rs[root]=newnode(mid+1,r,y); add(rs[root],x,y); } update(root); } int tsum(int root,int l,int r) { int lc=tl[root],rc=tr[root],mid=(lc+rc)>>1; if(l<=lc&&r>=rc) return tn[root]; int ans=0; if(l<=mid&&ls[root]) ans+=tsum(ls[root],l,r); if(r>mid&&rs[root]) ans+=tsum(rs[root],l,r); return ans; } int tmax(int root,int l,int r) { int lc=tl[root],rc=tr[root],mid=(lc+rc)>>1; if(l<=lc&&r>=rc) return tm[root]; int ans=0; if(l<=mid&&ls[root]) qmax(ans,tmax(ls[root],l,r)); if(r>mid&&rs[root]) qmax(ans,tmax(rs[root],l,r)); return ans; } int qsum(int u,int v,int x) { int ans=0; while(top[u]!=top[v]) { if(dep[top[u]]<dep[top[v]]) swap(u,v); ans+=tsum(rot[x],ran[top[u]],ran[u]); u=fa[top[u]]; } if(dep[u]>dep[v]) swap(u,v); return ans+tsum(rot[x],ran[u],ran[v]); } int qmx(int u,int v,int x) { int ans=0; while(top[u]!=top[v]) { if(dep[top[u]]<dep[top[v]]) swap(u,v); qmax(ans,tmax(rot[x],ran[top[u]],ran[u])); u=fa[top[u]]; } if(dep[u]>dep[v]) swap(u,v); return max(ans,tmax(rot[x],ran[u],ran[v])); } void change(int root,int x,int y) { int l=tl[root],r=tr[root],mid=(l+r)>>1; if(l==r) { tn[root]=tm[root]=y; return; } if(x<=mid) change(ls[root],x,y); else change(rs[root],x,y); update(root); } int main() { // freopen("test.in","r",stdin); scanf("%d%d",&n,&q); for(int i=1;i<=n;i++) scanf("%d%d",&a[i],&b[i]); for(int i=1;i<n;i++) { scanf("%d%d",&u,&v); add(u,v); }dep[1]=1; dfs1(1);dfs2(1,1); for(int i=0;i<=110000;i++) rot[i]=newnode(1,n+1); for(int i=1;i<=n;i++) add(rot[b[i]],ran[i],a[i]); while(q--) { if(getch()=='C') if(getch()=='C') { scanf("%d%d",&u,&v); change(rot[b[u]],ran[u],0); b[u]=v; add(rot[b[u]],ran[u],a[u]); } else { scanf("%d%d",&u,&v); change(rot[b[u]],ran[u],a[u]=v); } else if(getch()=='S') { scanf("%d%d",&u,&v); printf("%d\n",qsum(u,v,b[u])); } else { scanf("%d%d",&u,&v); printf("%d\n",qmx(u,v,b[u])); } } return 0; }