zoukankan      html  css  js  c++  java
  • AW353 雨天的尾巴 (【模板】线段树合并)

    题目地址


    易错点:

    • merge()时如果val==0应当把pos也设为0,这样就可以保证没有救济粮的情况下输出值为0.
    • 每次insert后val和pos一定都要更新.
    • 由于要求编号尽量小,pos更新时若tr[tr[p].ls].val>=tr[tr[p].rs].val则tr[p].pos=tr[tr[p].ls].pos.
    • dfs合并每个点的线段树时,一定要注意更新root[x]=merge(root[x],root[nowV],1,maxValue).

    #include<cstdio>
    #include<iostream>
    #include<algorithm>
    #include<queue>
    using namespace std;
    const int MAXN=2e5;
    struct Edge{
    	int from,to,nxt;
    }e[MAXN*2];
    int head[MAXN],edgeCnt=1;
    void addEdge(int u,int v){
    	e[++edgeCnt].from=u;
    	e[edgeCnt].to=v;
    	e[edgeCnt].nxt=head[u];
    	head[u]=edgeCnt;
    }
    int dep[MAXN],f[MAXN][25];
    void bfs(){
    	queue<int> q;
    	int s=1;
    	q.push(s);
    	dep[s]=1;
    	while(!q.empty()){
    		int nowU=q.front();q.pop();
    		for(int i=head[nowU];i;i=e[i].nxt){
    			int nowV=e[i].to;
    			if(dep[nowV])continue;
    			dep[nowV]=dep[nowU]+1;
    			f[nowV][0]=nowU;
    			for(int j=1;j<=20;j++){
    				f[nowV][j]=f[f[nowV][j-1]][j-1];
    			}
    			q.push(nowV);
    		}
    	}
    }
    int lca(int a,int b){
    	if(dep[a]>dep[b])swap(a,b);
    	for(int i=20;i>=0;i--){
    		if(dep[f[b][i]]>=dep[a])b=f[b][i];
    	}
    	if(a==b)return a;
    	for(int i=20;i>=0;i--){
    		if(f[a][i]!=f[b][i])
    			a=f[a][i],b=f[b][i];
    	}
    	return f[a][0];
    }
    struct Node{
    	int ls,rs;
    	int val,pos;
    }tr[MAXN*20*4];
    int nodeCnt=0;
    void insert(int &p,int l,int r,int x,int val){
    	if(!p)p=++nodeCnt;
    	if(l==r){
    		tr[p].val+=val;
    		tr[p].pos=l;
    		return;
    	}
    	int mid=(l+r)>>1;
    	if(x<=mid)insert(tr[p].ls,l,mid,x,val);
    	else if(x>mid)insert(tr[p].rs,mid+1,r,x,val);
    	tr[p].val=max(tr[tr[p].ls].val,tr[tr[p].rs].val);
    	tr[p].pos=tr[tr[p].ls].val>=tr[tr[p].rs].val?tr[tr[p].ls].pos:tr[tr[p].rs].pos;
    }
    int merge(int p,int q,int l,int r){
    	if(!p)return q;
    	if(!q)return p;
    	if(l==r){
    		tr[p].val+=tr[q].val;
    		tr[p].pos=tr[p].val?l:0;
    		return p;
    	}
    	int mid=(l+r)>>1;
    	tr[p].ls=merge(tr[p].ls,tr[q].ls,l,mid);
    	tr[p].rs=merge(tr[p].rs,tr[q].rs,mid+1,r);
    	tr[p].val=max(tr[tr[p].ls].val,tr[tr[p].rs].val);
    	tr[p].pos=tr[tr[p].ls].val>=tr[tr[p].rs].val?tr[tr[p].ls].pos:tr[tr[p].rs].pos;
    	return p;
    }
    int root[MAXN],ans[MAXN];
    int maxValue;
    void dfs(int x){
    	for(int i=head[x];i;i=e[i].nxt){
    		int nowV=e[i].to;
    		if(dep[nowV]>dep[x]){
    			dfs(nowV);
    			root[x]=merge(root[x],root[nowV],1,maxValue);
    		}
    	}
    	ans[x]=tr[root[x]].pos;
    }
    int X[MAXN],Y[MAXN],Z[MAXN];
    int vals[MAXN];
    int main(){
    	int n,m;
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n-1;i++){
    		int u,v;
    		scanf("%d%d",&u,&v);
    		addEdge(u,v);
    		addEdge(v,u);
    	}
    	bfs();
    	for(int i=1;i<=n;i++)
    		root[i]=++nodeCnt;
    	for(int i=1;i<=m;i++){
    		scanf("%d%d%d",&X[i],&Y[i],&Z[i]);
    		vals[i]=Z[i];
    	}
    	sort(vals+1,vals+1+m);
    	maxValue=unique(vals+1,vals+1+m)-(vals+1);
    	for(int i=1;i<=m;i++){
    		int x=X[i],y=Y[i];
    		int z=lower_bound(vals+1,vals+maxValue+1,Z[i])-vals;
    		int p=lca(x,y);
    		insert(root[x],1,maxValue,z,1);
    		insert(root[y],1,maxValue,z,1);
    		insert(root[p],1,maxValue,z,-1);
    		if(f[p][0])
    			insert(root[f[p][0]],1,maxValue,z,-1);
    	}
    	dfs(1);
    	for(int i=1;i<=n;i++){
    		printf("%d
    ",vals[ans[i]]);
    	}
    	return 0;
    }
  • 相关阅读:
    oracle中Blob和Clob类型的区别
    为什么要分库分表
    Enable file editing in Visual Studio's debug mode
    SQL Server Dead Lock Log
    Debug .NET Framework Source
    SQL Server text field里面有换行符的时候copy到excel数据会散乱
    诊断和修复Web测试记录器(Web Test Recorder)问题
    Can't load Microsoft.ReportViewer.ProcessingObjectModel.dll
    'telnet' is not recognized as an internal or external command
    Linq to XML
  • 原文地址:https://www.cnblogs.com/zbsy-wwx/p/11680532.html
Copyright © 2011-2022 走看看