zoukankan      html  css  js  c++  java
  • luogu P4556 【模板】线段树合并

    题目描述

    首先村落里的一共有 (n) 座房屋,并形成一个树状结构。然后救济粮分 (m) 次发放,每次选择两个房屋 ((x,~y)),然后对于 (x)(y) 的路径上(含 (x)(y))每座房子里发放一袋 (z) 类型的救济粮。

    然后深绘里想知道,当所有的救济粮发放完毕后,每座房子里存放的最多的是哪种救济粮。

    输入格式

    输入的第一行是两个用空格隔开的正整数,分别代表房屋的个数 (n) 和救济粮发放的次数 (m)

    (2) 到 第 (n) 行,每行有两个用空格隔开的整数 (a,~b),代表存在一条连接房屋 (a)(b) 的边。

    ((n + 1)) 到第 ((n + m)) 行,每行有三个用空格隔开的整数 (x,~y,~z),代表一次救济粮的发放是从 (x)(y) 路径上的每栋房子发放了一袋 (z) 类型的救济粮。

    输出格式

    输出 (n) 行,每行一个整数,第 (i) 行的整数代表 (i) 号房屋存放最多的救济粮的种类,如果有多种救济粮都是存放最多的,输出种类编号最小的一种。

    如果某座房屋没有救济粮,则输出 (0)


    #include<algorithm>
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<ctime>
    using namespace std;
    const int N=1e5+5;
    inline int read(){
    	int x=0;char c=getchar();
    	while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+c-48,c=getchar();
        return x;
    }
    int nxt[N<<1],head[N],go[N<<1],tot,Max;
    inline void add(int u,int v){
    	nxt[++tot]=head[u],head[u]=tot,go[tot]=v;
    	nxt[++tot]=head[v],head[v]=tot,go[tot]=u;
    }
    int n,m,Dep[N],f[N][21];
    void deal(int u,int father){
    	Dep[u]=Dep[father]+1;
    	for(int i=0;i<=19;i++)f[u][i+1]=f[f[u][i]][i];
    	for(int e=head[u];e;e=nxt[e]){
    		int v=go[e];
    		if(v==father)continue;
    		f[v][0]=u;
    		deal(v,u);
    	}
    }
    int LCA(int x,int y){
    	if(Dep[x]<Dep[y])swap(x,y);
    	for(int i=20;i>=0;i--)if(Dep[f[x][i]]>=Dep[y])x=f[x][i];
    	if(x==y)return x;
    	for(int i=20;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    	return f[x][0];
    }
    #define mid ((l+r)>>1)
    struct Seg{
    	int val,id,ls,rs;
    	#define ls(p) tree[p].ls
    	#define rs(p) tree[p].rs
    	#define id(p) tree[p].id
    	#define val(x) tree[x].val 
    }tree[N<<10];
    int root[N],num;
    inline void pushup(int a) {
        if(val(ls(a))<val(rs(a)))val(a)=val(rs(a)),id(a)=id(rs(a));
        else val(a)=val(ls(a)),id(a)=id(ls(a));
    }
    void update(int &p,int l,int r,int pos,int d){
    	if(!p)p=++num;
    	if(l==r){ val(p)+=d,id(p)=l; return ; }
    	if(pos<=mid)update(ls(p),l,mid,pos,d);
    	else update(rs(p),mid+1,r,pos,d);
    	pushup(p);
    }
    int merge(int l,int r,int u,int v){
    	if(!u||!v) return u|v;;
    	if(l==r){ val(u)+=val(v),id(u)=l; return u; }
    	ls(u)=merge(l,mid,ls(u),ls(v));
    	rs(u)=merge(mid+1,r,rs(u),rs(v));
    	pushup(u);
    	return u;
    }
    int ans[N];
    void dfs(int u){
    	for(int i=head[u];i;i=nxt[i]){
    		int v=go[i];
    		if(Dep[v]>Dep[u])dfs(v),root[u]=merge(1,Max,root[u],root[v]);
    	}
    	if(val(root[u]))ans[u]=id(root[u]);
    }
    int tx[N],ty[N],tz[N];
    signed main(){
    	n=read(),m=read();
    	for(int i=1;i<n;i++)add(read(),read());
    	deal(1,1);
    	for(int i=1;i<=m;i++)tx[i]=read(),ty[i]=read(),tz[i]=read(),Max=max(tz[i],Max);
    	for(int i=1,x,y,z;i<=m;i++){
    		x=tx[i],y=ty[i],z=tz[i];
    		int p=LCA(x,y);
    		update(root[x],1,Max,z,1);
    		update(root[y],1,Max,z,1);
    		update(root[p],1,Max,z,-1);
    		if(p!=1)update(root[f[p][0]],1,Max,z,-1);
    	}
    	dfs(1);
    	for(int i=1;i<=n;i++)printf("%d
    ",ans[i]);
    }
    
  • 相关阅读:
    Map小记
    一些Demo链接
    iOS小技巧
    更改AlertView背景
    UIlabel多行文字自动换行 (自动折行)
    设计模式-观察者模式 发布/订阅模式
    设计模式-策略模式
    设计模式-结构型模式-装饰模式
    设计模式-行为型模式-责任链模式
    设计模式-行为型模式-命令模式
  • 原文地址:https://www.cnblogs.com/naruto-mzx/p/13029005.html
Copyright © 2011-2022 走看看