zoukankan      html  css  js  c++  java
  • [bzoj3307] 雨天的尾巴

    Description

    N个点,形成一个树状结构。有M次发放,每次选择两个点x,y
    对于x到y的路径上(含x,y)每个点发一袋Z类型的物品。完成
    所有发放后,每个点存放最多的是哪种物品。

    Input

    第一行数字N,M
    接下来N-1行,每行两个数字a,b,表示a与b间有一条边
    再接下来M行,每行三个数字x,y,z.如题

    Output

    输出有N行
    每i行的数字表示第i个点存放最多的物品是哪一种,如果有
    多种物品的数量一样,输出编号最小的。如果某个点没有物品
    则输出0

    Solution

    树上差分+线段树合并,随便搞搞就好了。

    注意权值要离散化。

    #include<bits/stdc++.h>
    using namespace std;
     
    void read(int &x) {
        x=0;int f=1;char ch=getchar();
        for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
        for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    }
     
    void print(int x) {
        if(x<0) putchar('-'),x=-x;
        if(!x) return ;print(x/10),putchar(x%10+48);
    }
    void write(int x) {if(!x) putchar('0');else print(x);putchar('
    ');}
    
    const int maxn = 1e5+10;
    const int N = 1e5;
    
    int n,m,mp_cnt,rt[maxn],ls[maxn*50],rs[maxn*50],sum[maxn*50],seg,ans[maxn];
    
    map<int,int > mp;
    
    #define mid ((l+r)>>1)
    
    struct Segment_Tree {
    	void update(int p) {sum[p]=max(sum[ls[p]],sum[rs[p]]);}
    	void modify(int &p,int l,int r,int x,int z) {
    		if(!p) p=++seg;
    		if(l==r) return sum[p]+=z,void();
    		if(x<=mid) modify(ls[p],l,mid,x,z);
    		else modify(rs[p],mid+1,r,x,z);
    		update(p);
    	}
    	int query(int &p,int l,int r) {
    		if(!sum[p]) return 0;
    		if(l==r) return l;
    		if(sum[ls[p]]==sum[p]) return query(ls[p],l,mid);
    		else return query(rs[p],mid+1,r);
    	}
    	int merge(int x,int y) {
    		if(!x||!y) return x+y;
    		if((!ls[x])&&(!rs[x])&&(!ls[y])&&(!rs[y])) return sum[x]+=sum[y],x;
    		ls[x]=merge(ls[x],ls[y]);
    		rs[x]=merge(rs[x],rs[y]);
    		update(x);
    		return x;
    	}
    }SGT;
    
    struct Input_Tree {
    	int head[maxn],tot,f[maxn][20],dep[maxn];
    	struct edge{int to,nxt;}e[maxn<<1];
    
    	void add(int u,int v) {e[++tot]=(edge){v,head[u]},head[u]=tot;}
    	void ins(int u,int v) {add(u,v),add(v,u);}
    	
    	void dfs(int x,int fa) {
    		f[x][0]=fa,dep[x]=dep[fa]+1;
    		for(int i=1;i<=19;i++) f[x][i]=f[f[x][i-1]][i-1];
    		for(int i=head[x];i;i=e[i].nxt)
    			if(e[i].to!=fa) dfs(e[i].to,x);
    	}
    
    	int lca(int x,int y) {
    		if(dep[x]<dep[y]) swap(x,y);
    		for(int i=19;~i;i--) if(dep[f[x][i]]>=dep[y]) x=f[x][i];
    		if(x==y) return x;
    		for(int i=19;~i;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
    		return f[x][0];
    	}
    
    	void solve(int x,int fa) {
    		for(int i=head[x];i;i=e[i].nxt)
    			if(e[i].to!=fa) {
    				solve(e[i].to,x);
    				rt[x]=SGT.merge(rt[x],rt[e[i].to]);
    			}
    		ans[x]=SGT.query(rt[x],1,m);
    		if(!sum[rt[x]]) ans[x]=0;
    	}
    }T;
    
    int inx[maxn],iny[maxn],inz[maxn],r[maxn];
    
    int main() {
    	read(n),read(m);
    	for(int i=1,x,y;i<n;i++) read(x),read(y),T.ins(x,y);
    	T.dfs(1,0);
    	for(int i=1;i<=m;i++) read(inx[i]),read(iny[i]),read(inz[i]),r[i]=inz[i];
    	sort(r+1,r+m+1);
    	int M=unique(r+1,r+m+1)-r-1;
    	for(int i=1;i<=m;i++) inz[i]=lower_bound(r+1,r+M+1,inz[i])-r;
    	for(int i=1;i<=m;i++) {
    		int x=inx[i],y=iny[i],z=inz[i];
    		int t=T.lca(x,y);
    		SGT.modify(rt[x],1,m,z,1);
    		SGT.modify(rt[y],1,m,z,1);
    		SGT.modify(rt[t],1,m,z,-1);
    		if(T.f[t][0]) SGT.modify(rt[T.f[t][0]],1,m,z,-1);
    	}
    	T.solve(1,0);
    	for(int i=1;i<=n;i++) printf("%d
    ",r[ans[i]]);
    	return 0;
    }
    
  • 相关阅读:
    微信小程序学习系列(5) 微信小程序逻辑层
    微信小程序学习系列(4) 微信小程序架构文件
    微信小程序学习系列(3) 如何优雅的使用微信开发者工具
    使用Sqlserver 2012 导出表数据为SQL脚本
    Sqlserver2012 使用sql语句增加(或删除)表一个字段
    微信小程序学习系列(2) 使用AppId创建一个微信小程序
    微信小程序学习系列(1) 如何注册微信小程序
    微信小程序如何使用Vant
    vs2017搭建自己的nuget服务器
    使用swagger实现在线api文档自动生成 在线测试api接口
  • 原文地址:https://www.cnblogs.com/hbyer/p/10254482.html
Copyright © 2011-2022 走看看