• P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并 题解


    Link

    P4556 [Vani有约会]雨天的尾巴 /【模板】线段树合并

    Solve

    对于每个节点都减一颗权值线段树,然后再用差分的做法,最后统计答案的时候把线段树都合并起来,事实更新最优解

    这道题主要是模板,细节蛮多的,要注意

    Code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn=100005,maxe=200005;
    int N,M;
    int cnt,lnk[maxn],nxt[maxe],son[maxe];
    int tot,size[maxn],top[maxn],dep[maxn],max_son[maxn],F[maxn],root[maxn],Ans[maxn];
    int X[maxn],Y[maxn],Z[maxn],MAXR;
    
    struct node{
    	int lson,rson,x;
    	LL tot;
    }c[6000005];
    inline void add_e(int x,int y){son[++cnt]=y;nxt[cnt]=lnk[x];lnk[x]=cnt;}
    
    void DFS1(int x,int fa){
    	size[x]=1;int max_x=-(1<<30);
    	for(int j=lnk[x];j;j=nxt[j]){
    		if(son[j]==fa)continue;
    		dep[son[j]]=dep[x]+1;F[son[j]]=x;
    		DFS1(son[j],x);
    		size[x]+=size[son[j]];
    		if(size[son[j]]>max_x)max_x=size[son[j]],max_son[x]=son[j];
    	}
    	return ;
    }
    
    void DFS2(int x,int fa,int topf){
    	top[x]=topf;
    	for(int j=lnk[x];j;j=nxt[j]){
    		if(son[j]==fa)continue;
    		if(son[j]==max_son[x])DFS2(son[j],x,topf);
    		else DFS2(son[j],x,son[j]);
    	}
    }
    
    int LCA(int x,int y){
    	while(top[x]^top[y]){
    		if(dep[top[x]]<dep[top[y]])swap(x,y);
    		x=F[top[x]];
    	}
    	return dep[x]<dep[y]?x:y;
    }
    
    inline int build(){
    	++tot;c[tot].lson=c[tot].rson=c[tot].tot=c[tot].x=0;
    	return tot;
    }
    
    inline void push_up(int x){
    	if(c[c[x].lson].tot>=c[c[x].rson].tot)c[x].tot=c[c[x].lson].tot,c[x].x=c[c[x].lson].x;
    	else c[x].tot=c[c[x].rson].tot,c[x].x=c[c[x].rson].x;
    	return ;
    }
    
    int change(int x,int l,int r,int pos,int val){
    	if(!x)x=build();
    	if(l==r){c[x].tot+=val;c[x].x=l;return x;}
    	int mid=(r-l>>1)+l;
    	if(pos<=mid) c[x].lson=change(c[x].lson,l,mid,pos,val);
    	else c[x].rson=change(c[x].rson,mid+1,r,pos,val);
    	push_up(x);
    	return x;
    }
    
    int merge(int p,int q,int l,int r){
    	if(!p)return q;if(!q)return p;
    	if(l==r){c[p].tot+=c[q].tot;c[p].x=l;return p;}
    	int mid=(r-l>>1)+l;
    	c[p].lson=merge(c[p].lson,c[q].lson,l,mid);
    	c[p].rson=merge(c[p].rson,c[q].rson,mid+1,r);
    	push_up(p);
    	return p;
    }
    
    void DFS3(int x,int fa){
    	for(int j=lnk[x];j;j=nxt[j]){
    		if(son[j]==fa)continue;
    		DFS3(son[j],x);root[x]=merge(root[x],root[son[j]],1,MAXR);
    	}
    	if(c[root[x]].tot)Ans[x]=c[root[x]].x;
    	return ;
    }
    
    inline int read(){
    	int ret=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
    	return ret*f;
    }
    
    int main(){
    	freopen("P4556.in","r",stdin);
    	freopen("P4556.out","w",stdout);
    	N=read();M=read();
    	for(int i=1;i<N;i++){
    		int x=read(),y=read();
    		add_e(x,y);add_e(y,x);
    	}
    	dep[1]=1;DFS1(1,0);
    	DFS2(1,0,1);
    	for(int i=1;i<=M;i++){
    		X[i]=read(),Y[i]=read(),Z[i]=read();MAXR=max(MAXR,Z[i]);
    	}
    	for(int i=1;i<=M;i++){
    		int lca=LCA(X[i],Y[i]);
    		root[X[i]]=change(root[X[i]],1,MAXR,Z[i],1);
    		root[Y[i]]=change(root[Y[i]],1,MAXR,Z[i],1);
    		root[lca]=change(root[lca],1,MAXR,Z[i],-1);
    		if(F[lca])root[F[lca]]=change(root[F[lca]],1,MAXR,Z[i],-1);
    	}
    	DFS3(1,0);
    	for(int i=1;i<=N;i++)printf("%d
    ",Ans[i]);
    	return 0;
    }
    
  • 相关阅读:
    WebHttpRequest在sharepoint文档库中的使用
    使用log4net无法将日志记录插入mysql数据库解决办法
    通过WebClient模拟post上传文件到服务器
    webservice测试窗体只能用于来自本地计算机的请求
    rest api方式实现对文档库的管理
    咏南中间件支持即时通讯
    QJSON封装好的序列和还原方法
    ADO特有的流化和还原
    FIREMONEY手机虚拟键盘遮挡的解决
    安卓安装ZXING(二维码)SDK
  • 原文地址:https://www.cnblogs.com/martian148/p/14083836.html
Copyright © 2020-2023  润新知