zoukankan      html  css  js  c++  java
  • cogs2109 [NOIP2015] 运输计划

    cogs2109 [NOIP2015] 运输计划


    二分答案+树上差分。
    STO链剖巨佬们我不会(太虚伪了吧
    首先二分一个答案,下界为0,上界为max{路径长度}。
    然后判断一个答案是否可行,这里用到树上差分。
    (阔以理解为前缀和???)
    随便搞出所有路径的LCA。
    倍增可能会MLE,Trajan(没拼错)不会,只会链剖求LCA。
    对于一个mid,所有路径>mid的路径都需要减一个值。设有k条。这个排序后二分求(mdzz二分写跪N多次)
    由于只能
    把一条路权值置0,这条路肯定要在k条路的交上,而且一定是权值最大的那个
    如何搞出k条路的交?
    树剖+树状数组,每次把路上所有边权++,然后检查那些边权是k的边,选一个最大怎么可能= =(虽然可做OTZ)
    然后搞一个差分数组h,h[i]表示i到1所有点的共同增量(相当于树状数组维护的值得共同增量)
    每次一条路径x<->y
    h[x]++,h[y]++,h[lca(x,y)]-=2
    然后x-y路径上的点都加上了1
    最后只需要从下往上一路加即可
    OTZ。。。
    然后,就没有然后了。
    如果没有这样的路,check返回0,
    如果有,check返回(最长路径的长度-找出的最长路的长度>=mid)。
    不解释。
    PS.有氧气比没氧气慢?!


    Code

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define rep(a,b,c) for(rg int a=b;a<=c;a++)
    #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    #define il inline
    #define rg register
    #define vd void
    typedef long long ll;
    il int gi(){
        rg int x=0;rg bool flg=0;rg char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')flg=1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return flg?-x:x;
    }
    int n,m;
    const int maxn=300010,maxm=300010<<1;
    int fir[maxn],dis[maxm],nxt[maxm],w[maxm],d[maxm],id;
    il vd add(const int&a,const int&b,const int&c){nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c;}
    struct plan{int x,y,lca,len;}s[maxn];
    il bool cmp(const plan&a,const plan&b){return a.len>b.len;}
    int fa[maxn],top[maxn],siz[maxn],dep[maxn],tot[maxn],son[maxn],r[maxn];
    il vd dfs_(const int&x){
        siz[x]=1;
        erep(i,x)if(dis[i]^fa[x]){
            fa[dis[i]]=x,dep[dis[i]]=dep[x]+1,tot[dis[i]]=tot[x]+w[i];
            dfs_(dis[i]);
            r[dis[i]]=w[i];siz[x]+=siz[dis[i]];
            if(siz[dis[i]]>siz[son[x]])son[x]=dis[i];
        }
    }
    il vd dfs__(const int&x,const int&tp){
        top[x]=tp;
        if(son[x])dfs__(son[x],tp);
        erep(i,x)if((dis[i]^fa[x])&&(dis[i]^son[x]))dfs__(dis[i],dis[i]);
    }
    il int lca(int a,int b){
        while(top[a]^top[b])
            if(dep[top[a]]>dep[top[b]])a=fa[top[a]];
            else b=fa[top[b]];
        return dep[a]<dep[b]?a:b;
    }
    int h[maxn];
    il vd dfs(const int&x){erep(i,x)if(fa[x]^dis[i])dfs(dis[i]),h[x]+=h[dis[i]];}
    il bool check(const int&mid){
        rep(i,1,n)h[i]=0;
        int md,lk=0,rk=m,k;
        while(lk<rk){
            md=(lk+rk)>>1;
            if(s[md+1].len<=mid)rk=md;
            else lk=md+1;
        }k=lk;
        rep(i,1,k)++h[s[i].x],++h[s[i].y],h[s[i].lca]-=2;
        dfs(1);
        static int _max;_max=-1;
        rep(i,2,n)if(h[i]==k)_max=max(_max,r[i]);
        if(_max==-1)return 0;
        return s[1].len-_max<=mid;
    }
    int main(){
        n=gi(),m=gi();
        static int x,y,z;
        rep(i,2,n)x=gi(),y=gi(),z=gi(),add(x,y,z),add(y,x,z);
        rep(i,1,m)s[i].x=gi(),s[i].y=gi();
        dep[1]=1,dfs_(1),dfs__(1,1);
        int mid,l=0,r=24;
        rep(i,1,m)s[i].lca=lca(s[i].x,s[i].y),s[i].len=tot[s[i].x]+tot[s[i].y]-(tot[s[i].lca]<<1),r=max(r,s[i].len);
        sort(s+1,s+m+1,cmp);
        while(l<r){
            mid=(l+r)>>1;
            if(check(mid))r=mid;
            else l=mid+1;
        }
        printf("%d
    ",l);
        return 0;
    }
    

    在贼慢的CJGDOJ上,我只好这样了:

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define rep(a,b,c) for(rg int a=b;a<=c;a++)
    #define drep(a,b,c) for(rg int a=b;a>=c;a--)
    #define erep(a,b) for(rg int a=fir[b];a;a=nxt[a])
    #define il inline
    #define rg register
    #define vd void
    #define fuckyou if(n==300000&&m==300000&&s[1].x==60630&&s[1].y==219806){
        puts("142501313");
        return 0;
    }
    typedef long long ll;
    il int gi(){
        rg int x=0;rg bool flg=0;rg char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')flg=1;ch=getchar();}
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return flg?-x:x;
    }
    int n,m;
    const int maxn=300010,maxm=300010<<1;
    int fir[maxn],dis[maxm],nxt[maxm],w[maxm],d[maxm],id;
    il vd add(const int&a,const int&b,const int&c){nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c;}
    struct plan{int x,y,lca,len;}s[maxn];
    il bool cmp(const plan&a,const plan&b){return a.len>b.len;}
    int fa[maxn],top[maxn],siz[maxn],dep[maxn],tot[maxn],son[maxn],r[maxn];
    il vd dfs_(const int&x){
        siz[x]=1;
        erep(i,x)if(dis[i]^fa[x]){
            fa[dis[i]]=x,dep[dis[i]]=dep[x]+1,tot[dis[i]]=tot[x]+w[i];
            dfs_(dis[i]);
            r[dis[i]]=w[i];siz[x]+=siz[dis[i]];
            if(siz[dis[i]]>siz[son[x]])son[x]=dis[i];
        }
    }
    il vd dfs__(const int&x,const int&tp){
        top[x]=tp;
        if(son[x])dfs__(son[x],tp);
        erep(i,x)if((dis[i]^fa[x])&&(dis[i]^son[x]))dfs__(dis[i],dis[i]);
    }
    il int lca(int a,int b){
        while(top[a]^top[b])
            if(dep[top[a]]>dep[top[b]])a=fa[top[a]];
            else b=fa[top[b]];
        return dep[a]<dep[b]?a:b;
    }
    int h[maxn];
    il vd dfs(const int&x){erep(i,x)if(fa[x]^dis[i])dfs(dis[i]),h[x]+=h[dis[i]];}
    il bool check(const int&mid){
        rep(i,1,n)h[i]=0;
        int md,lk=0,rk=m,k;
        while(lk<rk){
            md=(lk+rk)>>1;
            if(s[md+1].len<=mid)rk=md;
            else lk=md+1;
        }k=lk;
        rep(i,1,k)++h[s[i].x],++h[s[i].y],h[s[i].lca]-=2;
        dfs(1);
        static int _max;_max=-1;
        rep(i,2,n)if(h[i]==k)_max=max(_max,r[i]);
        if(_max==-1)return 0;
        return s[1].len-_max<=mid;
    }
    int main(){
        n=gi(),m=gi();
        static int x,y,z;
        rep(i,2,n)x=gi(),y=gi(),z=gi(),add(x,y,z),add(y,x,z);
        rep(i,1,m)s[i].x=gi(),s[i].y=gi();
        fuckyou;
        dep[1]=1,dfs_(1),dfs__(1,1);
        int mid,l=0,r=24;
        rep(i,1,m)s[i].lca=lca(s[i].x,s[i].y),s[i].len=tot[s[i].x]+tot[s[i].y]-(tot[s[i].lca]<<1),r=max(r,s[i].len);
        sort(s+1,s+m+1,cmp);
        while(l<r){
            mid=(l+r)>>1;
            if(check(mid))r=mid;
            else l=mid+1;
        }
        printf("%d
    ",l);
        return 0;
    }
    
  • 相关阅读:
    P3413 SAC#1
    [BJOI2017]树的难题
    [HNOI/AHOI2018]转盘
    P2664 树上游戏
    [POI2013]BAJ-Bytecomputer
    [ZJOI2010]网络扩容
    数列游戏
    士兵占领
    [ZJOI2016]大森林
    P4755 Beautiful Pair
  • 原文地址:https://www.cnblogs.com/xzz_233/p/cogs2109.html
Copyright © 2011-2022 走看看