• Jzoj3625 旅行(travel)


    非常好的树剖模板题了,直接C颗线段树上去就好了,动态开点一次写对~

    #pragma GCC opitmize("O3")
    #pragma G++ opitmize("O3")
    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define N 100010
    #define mid (l+r>>1)
    using namespace std;
    struct edge{ int v,nt; } G[200010];
    struct nod{ int l,r,s,m; } s[3000010];
    int h[N],sz[N],top[N],son[N],f[N],d[N];
    int n,m,cnt=1,tot=0,clk=0,w[N],l[N],c[N],rt[N];
    inline void gmax(int& x,int y){ x<y?x=y:0; }
    inline void ps(nod& x){
    	x.s=s[x.l].s+s[x.r].s;
    	x.m=max(s[x.l].m,s[x.r].m);
    }
    inline void adj(int x,int y){ 
    	G[++cnt]=(edge){y,h[x]}; h[x]=cnt;
    	G[++cnt]=(edge){x,h[y]}; h[y]=cnt;
    }
    void dfs(int x,int p){
    	d[x]=d[p]+1; sz[x]=1; f[x]=p;
    	for(int v,i=h[x];i;i=G[i].nt)
    		if(!d[v=G[i].v]){
    			dfs(v,x); sz[x]+=sz[v];
    			if(sz[v]>sz[son[x]]) son[x]=v;
    		}
    }
    void dgs(int x,int p){
    	top[x]=p; l[x]=++clk;
    	if(son[x]) dgs(son[x],p);
    	for(int v,i=h[x];i;i=G[i].nt)
    		if(!l[v=G[i].v]) dgs(v,v);
    }
    void insert(int l,int r,int& x,int p,int k){
    	if(!x) x=++tot;
    	if(l==r) { s[x].s=s[x].m=k; return; }
    	if(p<=mid) insert(l,mid,s[x].l,p,k);
    		else insert(mid+1,r,s[x].r,p,k);
    	ps(s[x]);
    }
    void remove(int l,int r,int& x,int p){
    	if(l==r){ x=0; return; }
    	if(p<=mid) remove(l,mid,s[x].l,p);
    		else remove(mid+1,r,s[x].r,p);
    	if(s[x].l || s[x].r) ps(s[x]); else x=0;
    }
    void modify(int l,int r,int x,int p,int k){
    	if(l==r){ s[x].s=s[x].m=k; return; }
    	if(p<=mid) modify(l,mid,s[x].l,p,k);
    		else modify(mid+1,r,s[x].r,p,k);
    	ps(s[x]);
    }
    int queryS(int l,int r,int x,int L,int R){
    	if(!x) return 0;
    	if(L<=l && r<=R) return s[x].s;
    	int ans=0;
    	if(L<=mid) ans+=queryS(l,mid,s[x].l,L,R);
    	if(mid<R) ans+=queryS(mid+1,r,s[x].r,L,R);
    	return ans;
    }
    int gSum(int x,int y){
    	int ans=0,C=c[x];
    	for(;top[x]!=top[y];y=f[top[y]]){
    		if(d[top[x]]>d[top[y]]) swap(x,y);
    		ans+=queryS(1,n,rt[C],l[top[y]],l[y]);
    	}
    	if(d[x]>d[y]) swap(x,y);
    	return ans+queryS(1,n,rt[C],l[x],l[y]);
    }
    int queryM(int l,int r,int x,int L,int R){
    	if(!x) return 0;
    	if(L<=l && r<=R) return s[x].m;
    	int ans=0;
    	if(L<=mid) gmax(ans,queryM(l,mid,s[x].l,L,R));
    	if(mid<R) gmax(ans,queryM(mid+1,r,s[x].r,L,R));
    	return ans;
    }
    int gMax(int x,int y){
    	int ans=0,C=c[x];
    	for(;top[x]!=top[y];y=f[top[y]]){
    		if(d[top[x]]>d[top[y]]) swap(x,y);
    		gmax(ans,queryM(1,n,rt[C],l[top[y]],l[y]));
    	}
    	if(d[x]>d[y]) swap(x,y);
    	return max(ans,queryM(1,n,rt[C],l[x],l[y]));
    }
    int main(){
    	freopen("travel.in","r",stdin);
    	freopen("travel.out","w",stdout); 
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;++i) scanf("%d%d",w+i,c+i);
    	for(int x,y,i=1;i<n;++i) scanf("%d%d",&x,&y),adj(x,y); 
    	dfs(1,0); dgs(1,1); char o[3];
    	for(int i=1;i<=n;++i) insert(1,n,rt[c[i]],l[i],w[i]);
    	for(int x,y;m--;){
    		scanf("%s%d%d",o,&x,&y);
    		if(*o=='C'){
    			if(o[1]=='C'){
    				remove(1,n,rt[c[x]],l[x]);
    				insert(1,n,rt[y],l[x],w[x]);
    				c[x]=y;
    			} else {
    				modify(1,n,rt[c[x]],l[x],y);
    				w[x]=y;
    			}
    		} else {
    			if(o[1]=='S') printf("%d
    ",gSum(x,y));
    					else printf("%d
    ",gMax(x,y));
    		}
    	}
    }

  • 相关阅读:
    1442. Count Triplets That Can Form Two Arrays of Equal XOR
    1441. Build an Array With Stack Operations
    312. Burst Balloons
    367. Valid Perfect Square
    307. Range Sum Query
    1232. Check If It Is a Straight Line
    993. Cousins in Binary Tree
    1436. Destination City
    476. Number Complement
    383. Ransom Note
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477168.html
Copyright © 2020-2023  润新知