• [BZOJ 3307]雨天的尾巴


    3307: 雨天的尾巴

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 709  Solved: 296
    [Submit][Status][Discuss]

    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

    Sample Input

    20 50
    8 6
    10 6
    18 6
    20 10
    7 20
    2 18
    19 8
    1 6
    14 20
    16 10
    13 19
    3 14
    17 18
    11 19
    4 11
    15 14
    5 18
    9 10
    12 15
    11 14 87
    12 1 87
    14 3 84
    17 2 36
    6 5 93
    17 6 87
    10 14 93
    5 16 78
    6 15 93
    15 5 16
    11 8 50
    17 19 50
    5 4 87
    15 20 78
    1 17 50
    20 13 87
    7 15 22
    16 11 94
    19 8 87
    18 3 93
    13 13 87
    2 1 87
    2 6 22
    5 20 84
    10 12 93
    18 12 87
    16 10 93
    8 17 93
    14 7 36
    7 4 22
    5 9 87
    13 10 16
    20 11 50
    9 16 84
    10 17 16
    19 6 87
    12 2 36
    20 9 94
    9 2 84
    14 1 94
    5 5 94
    8 17 16
    12 8 36
    20 17 78
    12 18 50
    16 8 94
    2 19 36
    10 18 36
    14 19 50
    4 12 50

    Sample Output

    87
    36
    84
    22
    87
    87
    22
    50
    84
    87
    50
    36
    87
    93
    36
    94
    16
    87
    50
    50
    1<=N,M<=100000
    1<=a,b,x,y<=N
    1<=z<=10^9

    解题报告

    线段树启发式暴力合并

    首先我们肯定会想到简单的树剖套线段树套权值线段树的做法,但显然,假如数据卡你的话,是可以随便卡掉的,$MLE$+$RE$

    所以我们不能在大范围的区间进行权值线段树的开点与修改,于是我们考虑差分

    我们在树上的每一个节点开一棵权值线段树,动态开点保证空间,然后在树上差分,路径两端点对应加1,$LCA$与$LCA$父节点对应减1,就可以达到差分的效果了,最后$dfs$合并线段树统计答案即可

     1 #include <iostream>
     2 #include <cstring>
     3 #include <cstdio>
     4 using namespace std;
     5 inline int read(){
     6     int sum(0);char ch(getchar());
     7     for(;ch<'0'||ch>'9';ch=getchar());
     8     for(;ch>='0'&&ch<='9';sum=sum*10+(ch^48),ch=getchar());
     9     return sum;
    10 }
    11 const int mxv(1e9);
    12 struct edge{int e;edge *n;}*pre[100005];
    13 inline void insert(int s,int e){edge *tmp(new edge);tmp->e=e;tmp->n=pre[s];pre[s]=tmp;}
    14 int n,m,fa[100005][20],dep[100005];
    15 inline void dfs(int u){
    16     for(int i=1;(1<<i)<=dep[u];++i)fa[u][i]=fa[fa[u][i-1]][i-1];
    17     for(edge *i=pre[u];i;i=i->n){
    18         int e(i->e);if(e==fa[u][0])continue;
    19         fa[e][0]=u;dep[e]=dep[u]+1;dfs(e);
    20     }
    21 }
    22 inline int lca(int x,int y){
    23     if(dep[x]<dep[y])swap(x,y);
    24     int delta(dep[x]-dep[y]);
    25     for(int i=0;delta;++i)if(delta&(1<<i))delta^=1<<i,x=fa[x][i];
    26     if(x==y)return x;
    27     for(int i=19;i>=0;--i)if(fa[x][i]^fa[y][i])x=fa[x][i],y=fa[y][i];return fa[x][0];
    28 }
    29 #define get_mx(x) (x?x->mx:0)
    30 #define get_pos(x) (x?x->pos:0)
    31 struct node{
    32     node *lch,*rch;
    33     int mx;
    34     node():lch(NULL),rch(NULL),mx(0){}
    35     inline void pushup(){this->mx=max(get_mx(this->lch),get_mx(this->rch));}
    36 }*root[100005];
    37 inline void update(node *&x,int pos,int w,int l,int r){
    38     if(!x){x=new node();}
    39     if(l==r){x->mx+=w;/*cout<<' '<<l<<' '<<r<<endl;*/return;}
    40     int mid((l+r)>>1);
    41     if(pos<=mid)update(x->lch,pos,w,l,mid);
    42     else update(x->rch,pos,w,mid+1,r);x->pushup();
    43 }
    44 int ans[100005];
    45 inline void merge(node *&x,node *&y,int l,int r){
    46     if(!y)return;if(!x){x=y;return;}
    47     if(l==r){x->mx+=y->mx;return;}
    48     int mid((l+r)>>1);
    49     merge(x->lch,y->lch,l,mid);merge(x->rch,y->rch,mid+1,r);
    50     x->pushup();
    51 }
    52 inline int query(node *x,int ll,int rr,int l,int r){
    53     if(!x)return 0;if(ll<=l&&r<=rr)return x->mx;int mid((l+r)>>1),ret(0);
    54     if(ll<=mid)ret=query(x->lch,ll,rr,l,mid);if(mid<rr)ret=max(ret,query(x->rch,ll,rr,mid+1,r));return ret;
    55 }
    56 inline int query_pos(node *x,int l,int r,int mx){
    57     if(!x)return 0;if(l==r)return l;int mid((l+r)>>1);//cout<<l<<' '<<r<<' '<<mx<<' '<<get_mx(x->lch)<<endl;
    58     if(get_mx(x->lch)==mx)return query_pos(x->lch,l,mid,mx);
    59     return query_pos(x->rch,mid+1,r,mx);
    60 }
    61 /*inline void print(node *x){
    62     if(!x)return;
    63     printf("%d %d %d %d
    ",x->l,x->r,x->mx,x->pos);
    64     print(x->lch);print(x->rch);
    65 }*/
    66 inline void cal(int u){
    67     for(edge *i=pre[u];i;i=i->n){
    68         int e(i->e);if(e==fa[u][0])continue;
    69         cal(e);merge(root[u],root[e],1,mxv);//cout<<"print "<<u<<endl;print(root[u]);
    70     }
    71     ans[u]=query(root[u],1,mxv,1,mxv);/*cout<<ans[u]<<' ';*/ans[u]=query_pos(root[u],1,mxv,ans[u]);//cout<<ans[u]<<endl;
    72 }
    73 int main(){
    74     n=read(),m=read();for(int i=1;i<n;++i){int x(read()),y(read());insert(x,y);insert(y,x);}dfs(1);
    75     while(m--){
    76         int x(read()),y(read()),z(read()),tp(lca(x,y));
    77         update(root[x],z,1,1,mxv);update(root[y],z,1,1,mxv);update(root[tp],z,-1,1,mxv);update(root[fa[tp][0]],z,-1,1,mxv);
    78     }
    79     cal(1);for(int i=1;i<=n;++i)printf("%d
    ",ans[i]);
    80 }
    81 
    View Code
  • 相关阅读:
    第 6 章 Android SDK 版本与兼容
    第 5 章 第二个 activity
    第 4 章 Android 应用的调试
    第 3 章 Activity 的生命周期
    第 2 章 Android 与 MVC 设计模式
    第 1 章 Android 应用初体验
    ACM基础之线性结构:一刷 参考答案
    小马慢慢跑
    Ubuntu 利用 xinetd 限制 SSH 连接数
    C# 定制 Attribute 简单使用
  • 原文地址:https://www.cnblogs.com/hzoi-mafia/p/7753054.html
Copyright © 2020-2023  润新知