• 树链剖分【洛谷P4114】 Qtree1


    P4114 Qtree1

    题目描述

    给定一棵n个节点的树,有两个操作:

    • CHANGE i ti 把第i条边的边权变成ti
    • QUERY a b 输出从a到b的路径中最大的边权,当a=b的时候,输出0

    码农题。

    话说我码得变快了啊,虽然跟顾z吹45分钟码完Qtree没有完成,不过总共用了55分钟还是不长的嘿嘿。

    code:

    #include <iostream>
    #include <cstdio>
    
    #define ls(o) o<<1
    #define rs(o) o<<1|1
    
    #define int long long
    
    using namespace std;
    
    const int wx=500017;
    
    int head[wx],dfn[wx],size[wx],f[wx][23],dis[wx][23],dep[wx];
    int son[wx],a[wx],top[wx],tid[wx];
    int n,num,tot;
    char opt[17];
    
    inline int read(){
    	int sum=0,f=1; char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();}
    	while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0'; ch=getchar();}
    	return sum*f;
    }
    
    /*~~~~~~~~~~~~~~~~~~~ * ~~~~~~~~~~~~~~~~~~~~*/
    
    struct e{
    	int nxt,to,dis;
    }edge[wx*2];
    
    void add(int from,int to,int dis){
    	edge[++num].nxt=head[from];
    	edge[num].to=to;
    	edge[num].dis=dis;
    	head[from]=num;
    }
    
    int first_dfs(int u,int fa){
    	size[u]=1; int maxson=-1; dep[u]=dep[fa]+1;
    	dis[u][0]=a[u];
    	f[u][0]=fa;
    	for(int i=head[u];i;i=edge[i].nxt){
    		int v=edge[i].to;
    		if(v==fa)continue;
    		a[v]=edge[i].dis;
    		first_dfs(v,u);
    		size[u]+=size[v];
    		if(size[v]>maxson){
    			maxson=size[v]; son[u]=v;
    		}
    	}
    }
    
    int second_dfs(int u,int topf){
    	dfn[u]=++tot; top[u]=topf; tid[tot]=u;
    	if(son[u])second_dfs(son[u],topf);
    	for(int i=head[u];i;i=edge[i].nxt){
    		int v=edge[i].to;
    		if(dfn[v]||v==f[u][0])continue;
    		second_dfs(v,v);
    	}
    }
    /*~~~~~~~~~~~~~~~~~~~ * ~~~~~~~~~~~~~~~~~~~~*/
    
    
    /*~~~~~~~~~~~~~~~~~ SGT~~~~~~~~~~~~~~~~~~~~~*/
    
    struct SGT{
    	int l,r,tag,ma;
    	#define tag(o) t[o].tag
    	#define ma(o) t[o].ma
    }t[wx*4];
    
    void up(int o){
    	ma(o)=max(ma(ls(o)),ma(rs(o)));
    } 
    
    void down(int o){
    	if(tag(o)!=-1){
    		ma(ls(o))=tag(o); ma(rs(o))=tag(o);
    		tag(ls(o))=tag(o); tag(rs(o))=tag(o);
    		tag(o)=-1;
    	}
    }
    
    void build(int o,int l,int r){
    	t[o].l=l; t[o].r=r; tag(o)=-1;
    	if(l==r){ma(o)=a[tid[l]]; return ;}
    	int mid=t[o].l+t[o].r>>1;
    	if(l<=mid)build(ls(o),l,mid);
    	if(r>mid)build(rs(o),mid+1,r);
    	up(o);
    }
    
    void update_SGT(int o,int l,int r,int k){
    	if(l<=t[o].l&&t[o].r<=r){
    		ma(o)=k; tag(o)=k;
    		return ;
    	}
    	down(o);
    	int mid=t[o].l+t[o].r>>1;
    	if(l<=mid)update_SGT(ls(o),l,r,k);
    	if(r>mid)update_SGT(rs(o),l,r,k);
    	up(o);
    }
    
    int query_SGT(int o,int l,int r){
    	if(l>r)return 0;
    	if(l<=t[o].l&&t[o].r<=r){
    		return ma(o);
    	}
    	down(o); int maxn=-1;
    	int mid=t[o].l+t[o].r>>1;
    	if(l<=mid)maxn=max(maxn,query_SGT(ls(o),l,r));
    	if(r>mid)maxn=max(maxn,query_SGT(rs(o),l,r));
    	return maxn;
    }
    
    /*~~~~~~~~~~~~~~~~~ SGT~~~~~~~~~~~~~~~~~~~~~*/
    
    /*~~~~~~~~~~~~~~~~~ LCA~~~~~~~~~~~~~~~~~~~~~*/
    
    void pre(){
    	for(int j=1;j<=21;j++)for(int i=1;i<=n;i++)f[i][j]=f[f[i][j-1]][j-1],dis[i][j]=max(dis[f[i][j-1]][j-1],dis[i][j-1]);
    }
    
    int find(int x,int y){
    	if(dep[x]<dep[y])swap(x,y);
    	int re=-1;
    	for(int i=21;i>=0;i--){
    		if(dep[f[x][i]]>=dep[y]){
    			re=max(re,dis[x][i]);
    			x=f[x][i];
    		}
    	}
    	if(x==y)return re;
    	for(int i=21;i>=0;i--){
    		if(f[x][i]!=f[y][i]){
    			re=max(re,max(dis[x][i],dis[y][i]));
    			x=f[x][i]; y=f[y][i];
    		}
    	}
    	return max(re,max(dis[x][0],dis[y][0]));
    }
    
    int LCA(int x,int y){
    	if(dep[x]<dep[y])swap(x,y);
    	for(int i=21;i>=0;i--){
    		if(dep[f[x][i]]>=dep[y]){
    			x=f[x][i];
    		}
    	}
    	if(x==y)return x;
    	for(int i=21;i>=0;i--){
    		if(f[x][i]!=f[y][i]){
    			x=f[x][i]; y=f[y][i];
    		}
    	}
    	return f[x][0];
    }
    
    /*~~~~~~~~~~~~~~~~~ LCA~~~~~~~~~~~~~~~~~~~~~*/
    
    /*~~~~~~~~~~~~~~~~~ shu pou~~~~~~~~~~~~~~~~~*/
    
    void update(int x,int y,int k){
    	int fx=top[x]; int fy=top[y];
    	while(fx!=fy){
    		if(dep[fx]>=dep[fy])update_SGT(1,dfn[fx],dfn[x],k),x=f[fx][0];
    		else update_SGT(1,dfn[fy],dfn[y],k),y=f[fy][0];
    		fx=top[x]; fy=top[y];
    	}
    	if(dfn[x]>dfn[y])swap(x,y);
    	update_SGT(1,dfn[x],dfn[y],k);
    }
    
    int query(int x,int y){
    	int fx=top[x]; int fy=top[y]; int re=-1;
    	while(fx!=fy){
    		if(dep[fx]>=dep[fy])re=max(re,query_SGT(1,dfn[fx],dfn[x])),x=f[fx][0];
    		else re=max(re,query_SGT(1,dfn[fy],dfn[y])),y=f[fy][0];
    		fx=top[x]; fy=top[y];
    	}
    	if(dfn[x]>dfn[y])swap(x,y);
    	re=max(re,query_SGT(1,dfn[x],dfn[y]));
    	return re;
    }
    
    /*~~~~~~~~~~~~~~~~~ shu pou~~~~~~~~~~~~~~~~~*/
    signed main(){
    	n=read();
    	for(int i=1;i<n;i++){
    		int x,y,z;
    		x=read(); y=read(); z=read();
    		add(x,y,z); add(y,x,z);
    	}
    	first_dfs(1,0); second_dfs(1,1); build(1,1,n); pre();
    	while(1){
    		scanf("%s",opt+1);
    		if(opt[1]=='D')break;
    		if(opt[1]=='Q'){
    			int x,y;
    			x=read(); y=read();
    			if(x==y)puts("0");
    			else{	
    				int lca=LCA(x,y);
    				int tmp=query_SGT(1,dfn[lca],dfn[lca]);
    				update_SGT(1,dfn[lca],dfn[lca],-521);
    				printf("%lld
    ",query(x,y));
    				update_SGT(1,dfn[lca],dfn[lca],tmp);
    			}
    		}
    		if(opt[1]=='C'){
    			int x,y;
    			x=read(); y=read();
    			int x1=edge[x*2-1].to;
    			int x2=edge[x*2].to;
    			if(dep[x1]>dep[x2])x=x1;
    			else x=x2;
    			update(x,x,y);
    		}
    	}
    	return 0;
    }
    
    /*
    
    3
    1 2 1
    2 3 2
    QUERY 1 2
    CHANGE 1 3
    QUERY 1 2
    DONE
    
    */
  • 相关阅读:
    UE4智能指针:TUniquePtr
    浅析UE4垃圾回收
    UE4中资源的引用
    ELF文件基础
    【JVM】JVM和Java 体系架构
    【Java多线程】Java线程生命周期、线程同步、线程通信(二)
    【Java多线程】Java多线程基础(一)
    【Java面试题】MySQL索引底层为什么用到B+树
    【算法】B树、B+树详解
    【Kafka】 Kafka的简介与架构(三)
  • 原文地址:https://www.cnblogs.com/wangxiaodai/p/9858816.html
Copyright © 2020-2023  润新知