BZOJ3307——雨天的尾巴

来源:互联网 发布:mac 打字声音 编辑:程序博客网 时间:2024/04/30 10:48

1、题意:给一棵树,m次操作把一个链都添加一种物品,问每个点哪种物品最多。
2、分析:如果我们暴力上链剖的话,时间和空间都会boom!
那么我们考虑树上差分!那么就变成了把从根到某个点添加或删除一种物品。在树上打标记,我们dfs的时候顺便用线段树合并当前这个点的物品。

#include<map>#include<set>#include<cmath>#include<queue>#include<stack>#include<vector>#include<bitset>#include<string>#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>using namespace std;#define M 100010#define pb push_back#define LL long long#define MOD 1000000007#define inf 2147483647#define pii pair<int,int>#define llinf 4000000000000000000ll#define For(i,x,y) for(int i=(x);i<(y);i++)#define rep(i,x,y) for(int i=(x);i<=(y);i++)#define drep(i,x,y) for(int i=(x);i>=(y);i--)inline int read(){    char ch=getchar();int x=0,f=1;    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}inline LL llread(){    char ch=getchar();LL x=0,f=1;    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}    while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}    return x*f;}struct Edge{    int v,Next;} G[M*2];int head[M],tot;int ft[M][20],height[M],en;inline void add(int u,int v){    G[++tot]=(Edge){v,head[u]};head[u]=tot;    G[++tot]=(Edge){u,head[v]};head[v]=tot;}inline void dfs(int x){    height[x]=height[ft[x][0]]+1;    for(int i=head[x];i!=-1;i=G[i].Next)if(G[i].v!=ft[x][0]){        ft[G[i].v][0]=x;dfs(G[i].v);    }}inline void init(int n){    For(j,1,20)rep(i,1,n)ft[i][j]=ft[ft[i][j-1]][j-1];}inline int lca(int x,int y){    if(height[x]>height[y])swap(x,y);    int t=height[y]-height[x];    For(i,0,20)if((1<<i)&t)y=ft[y][i];    if(x==y)return x;    drep(i,19,0)if(ft[x][i]!=ft[y][i])x=ft[x][i],y=ft[y][i];    return ft[x][0];}struct que{    int x,y,z;} a[M];int b[M],wt[M];struct lz{    int x,d;} q[M*40];vector<lz> h[M];int T[M*40],ls[M*40],rs[M*40],total,res[M];inline lz mx(lz x,lz y){return (x.x>y.x||x.x==y.x&&x.d<y.d)?x:y;}inline void insert(int l,int r,int &o,int x,int y){    if(!o)o=++total;if(l==r){q[o].x+=y;q[o].d=x;return;}int mid=(l+r)/2;    if(x<=mid)insert(l,mid,ls[o],x,y);else insert(mid+1,r,rs[o],x,y);    q[o]=mx(q[ls[o]],q[rs[o]]);}inline int merge(int l,int r,int x,int y){    if(!x||!y)return x+y;if(l==r){        q[x].x+=q[y].x;return x;    }int mid=(l+r)/2;ls[x]=merge(l,mid,ls[x],ls[y]);    rs[x]=merge(mid+1,r,rs[x],rs[y]);q[x]=mx(q[ls[x]],q[rs[x]]);return x;}inline lz query(int l,int r,int o){return q[o];} inline void solve(int x){    For(i,0,h[x].size())insert(1,en,T[x],h[x][i].x,h[x][i].d);    for(int i=head[x];i!=-1;i=G[i].Next)if(G[i].v!=ft[x][0]){        solve(G[i].v);T[x]=merge(1,en,T[x],T[G[i].v]);    }res[x]=query(1,en,T[x]).d;}int main(){    //freopen("0input.in","r",stdin);//freopen(".out","w",stdout);    int n=read(),m=read();memset(head,-1,sizeof(head));    For(i,1,n)add(read(),read());dfs(1);init(n);rep(i,1,m){        a[i]=(que){read(),read(),read()};wt[i]=b[i]=a[i].z;        if(height[a[i].x]<height[a[i].y])swap(a[i].x,a[i].y);    }sort(b+1,b+m+1);int tt=unique(b+1,b+m+1)-b-1;int xt;rep(i,1,m){        xt=lower_bound(b+1,b+tt+1,a[i].z)-b,wt[xt]=a[i].z,a[i].z=xt;    }en=tt;rep(i,1,m){        que x=a[i];int LCA=lca(x.x,x.y);if(LCA!=x.y){            h[LCA].pb((lz){x.z,-1});h[x.y].pb((lz){x.z,1});        }h[ft[LCA][0]].pb((lz){x.z,-1});h[x.x].pb((lz){x.z,1});    }solve(1);rep(i,1,n)printf("%d\n",wt[res[i]]);    return 0;}
1 0
原创粉丝点击