zoukankan      html  css  js  c++  java
  • BZOJ3307: 雨天的尾巴

    中文题意简单易懂 不再叙述

    题解: 很明显我们考虑到运用树上差分的思想 加入这个元素等于在u,v位置加入 删除等于在lca(u,v)和fa[lca(u,v)]的地方-1 这样问题就转化成 从叶子节点dfs将这些点操作 并查询区间num最大且vul最小的值即可 这样我们可以通过线段树维护 然后本题的一个难点就是线段树合并了吧 讲道理 以前的合并的题都是启发式合并 但是这个题有个性质就是你用线段树维护 那么你就只需要将都有的节点从小到上更新 没有的之间连上去即可 然后就做完了  复杂度均摊下来应该是nlogn 空间复杂度同理也是nlogn

    #include <bits/stdc++.h>
    #define pii pair<int,int>
    const int MAXN=1e5+10;
    #define ll long long
    using namespace std;
    int n,m;
    vector<int>vec[MAXN];
    ll read(){
        ll x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
        while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    int fa[MAXN],num[MAXN],dep[MAXN],son[MAXN];
    void dfs1(int v,int pre,int deep){
        num[v]=1;fa[v]=pre;dep[v]=deep+1;
        for(int i=0;i<vec[v].size();i++){
    	if(vec[v][i]!=pre){
    	    dfs1(vec[v][i],v,deep+1);
    	    num[v]+=num[vec[v][i]];
    	    if(son[v]==-1||num[son[v]]<num[vec[v][i]])son[v]=vec[v][i];
    	}
        }
    }
    int p[MAXN],fp[MAXN],cnt,tp[MAXN],sz;
    void dfs2(int v,int td){
        p[v]=++cnt;fp[p[v]]=v;tp[v]=td;
        if(son[v]!=-1)dfs2(son[v],td);
        for(int i=0;i<vec[v].size();i++){
    	if(vec[v][i]!=son[v]&&vec[v][i]!=fa[v])dfs2(vec[v][i],vec[v][i]);
        }
    }
    int Lca(int u,int v){
        int uu=tp[u];int vv=tp[v];
        while(uu!=vv){
    	if(dep[uu]<dep[vv])swap(uu,vv),swap(u,v);
    	u=fa[uu];uu=tp[u];
        }
        if(dep[u]>dep[v])swap(u,v);
        return u;
    }
    typedef struct que{
        int u,v,c,lca;
    }que;
    que q[MAXN];
    vector<int>v1;
    vector<pii>v2[MAXN];
    typedef struct node{
        int num,maxx,l,r;
    }node;
    node d[MAXN*16*4];int ans[MAXN],rt[MAXN];
    void up(int x){
        if(!d[x].l&&!d[x].r)return ;
        d[x].num=0;
        if(d[x].l){d[x].num=d[d[x].l].num;d[x].maxx=d[d[x].l].maxx;}
        if(d[x].r){
    	if(!d[x].num)d[x].num=d[d[x].r].num,d[x].maxx=d[d[x].r].maxx;
    	else {
    	    if(d[x].num<d[d[x].r].num)d[x].num=d[d[x].r].num,d[x].maxx=d[d[x].r].maxx;
    	    else if(d[x].num==d[d[x].r].num)d[x].maxx=min(d[x].maxx,d[d[x].r].maxx);
    	}
        }
    }
    int cnt1;
    void update(int &rt,int l,int r,int t,int vul){
        if(!rt)rt=++cnt1;   
        if(l==r){d[rt].num+=vul;d[rt].maxx=l;return ;}
        int mid=(l+r)>>1;
        if(t<=mid)update(d[rt].l,l,mid,t,vul);
        else update(d[rt].r,mid+1,r,t,vul);
        up(rt);
    }
    void merge(int &x,int y,int l,int r){
        if(!x&&!y)return ;
        if(x&&y){
    	if(l==r){
    	    d[x].num+=d[y].num;return ;
    	}
    	int mid=(l+r)>>1;
    	merge(d[x].l,d[y].l,l,mid);
    	merge(d[x].r,d[y].r,mid+1,r);
        }
        else{
    	if(y)x=y;
    	return ;
        }
        up(x);
    }
    void dfs(int v){
        for(int i=0;i<vec[v].size();i++){
    	if(vec[v][i]!=fa[v]){
    	    dfs(vec[v][i]);
    	    merge(rt[v],rt[vec[v][i]],1,sz);
    	}
        }
        for(int i=0;i<v2[v].size();i++){
    	update(rt[v],1,sz,v2[v][i].first,v2[v][i].second);}
       // cout<<d[rt[v]].num<<"====:::"<<" "<<v<<endl;
       // for(int i=0;i<v2[v].size();i++)cout<<v2[v][i].first<<" "<<v2[v][i].second<<endl;
        if(!d[rt[v]].num)ans[v]=0;
        else ans[v]=d[rt[v]].maxx;
    }
    int main(){
        n=read();m=read();
        for(int i=1;i<=n;i++)son[i]=-1;
        int u,v;
        for(int i=1;i<n;i++)u=read(),v=read(),vec[u].push_back(v),vec[v].push_back(u);
        dfs1(1,0,0);dfs2(1,1);
        for(int i=1;i<=m;i++)q[i].u=read(),q[i].v=read(),q[i].c=read(),v1.push_back(q[i].c),q[i].lca=Lca(q[i].u,q[i].v);
        //for(int i=1;i<=m;i++)cout<<q[i].lca<<" ";
        //cout<<endl;
        sort(v1.begin(),v1.end());
        sz=unique(v1.begin(),v1.end())-v1.begin();
     //   built(1,1,sz);
        for(int i=1;i<=m;i++){
    	q[i].c=lower_bound(v1.begin(),v1.begin()+sz,q[i].c)-v1.begin()+1,v2[q[i].u].push_back(make_pair(q[i].c,1));
    	v2[q[i].v].push_back(make_pair(q[i].c,1));v2[q[i].lca].push_back(make_pair(q[i].c,-1));
    	v2[fa[q[i].lca]].push_back(make_pair(q[i].c,-1));
        }
        dfs(1);
        for(int i=1;i<=n;i++){
    	if(!ans[i])puts("0");
    	else printf("%d
    ",v1[ans[i]-1]);
        }
        return 0;
    }
    

    3307: 雨天的尾巴

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 1004  Solved: 400
    [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

  • 相关阅读:
    协议分析 - DHCP协议解码详解
    在SqlServer2000的视图中小心使用*符号
    sql 将 varchar 值转换为数据类型为 int 的列时发生语法错误 的解决办法
    LECCO SQL Expert工具之优化sql语句
    css+js简单应用
    对任何一天是星期几算法的实现
    asp.net ajax 1.0 出现"sys"未定义解决方法
    js日历脚本
    在ASP.NET中重写URL
    在ASP.NET中重写URL (续篇)
  • 原文地址:https://www.cnblogs.com/wang9897/p/9141393.html
Copyright © 2011-2022 走看看