• 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));
    		}
    	}
    }

  • 相关阅读:
    ASP.NET MVC下的四种验证编程方式
    tp框架下,数据库和编辑器都是utf-8, 输出中文却还是乱码
    按拼音首字母排序
    PHP 文件导出(Excel, CSV,txt)
    RedisDesktopManager 可视化工具提示:无法加载键:Scan..
    window下redis如何查看版本号
    jQuery 防止相同的事件快速重复触发
    input中加入搜索图标
    JS搜索商品(跟外卖app店内搜索商品一样) ,keyup函数和click函数调用
    JS正则对象 RegExp(有变量的时候使用),用来匹配搜索关键字(标红)
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/9477168.html
Copyright © 2020-2023  润新知