zoukankan      html  css  js  c++  java
  • 【bzoj3218】a + b Problem 【网络流】【最小割】【主席树】

    题目传送门
    题解:
    考虑一种朴素的连边:
    S>iw[i]
    i>Tb[i]
    i>ip[i]
    j>i(1j<i,l[i]a[j]r[i])inf
    然后用i=1nb[i]+w[i]减去最小割就是答案。
    但是这样连边有n2级别的边数,n5000,显然不行。
    于是我们就有了一些神奇的操作:主席树优化连边!
    先把a,l,r进行一波离散化。
    连边方法:
    S>iw[i]
    i>Tb[i]
    i>ip[i]
    主席树上,儿子向父亲连边,容量inf。
    当要创建一个新版本时,上一个版本原来位置的节点向新增的log n个相同位置的节点连边,容量inf。新增的节点向其父亲连边,容量infia[i]在线段树上对应的叶子节点连边。
    然后第i1个版本中[l[i],r[i]]在树上对应的一堆区间节点向i连边,容量inf
    详细解释可以去看PoPoQQQ神犇的博客
    吐槽:为什么我的常数那么大!为什么我的代码那么矬!
    UPD:网络流模板有问题,work数组简直就是害人的!增加运行时间的利器!
    代码:

    #include<cstdio>
    #include<cstring>
    #include<queue>
    #include<algorithm>
    using namespace std;
    typedef long long ll;
    const int N=5005,M=1200005,inf=0x7fffffff;
    int n,tot=1,a[N],b[N],w[N],l[N],r[N],p[N],Hash[N];
    int cnt=1,s=0,t=1,root[N],head[M],work[M],to[M],nxt[M],dd[M],dep[M],ch[M][2];
    ll ans;
    queue<int> q;
    void adde(int u,int v,int d){
        to[++cnt]=v;
        nxt[cnt]=head[u];
        dd[cnt]=d;
        head[u]=cnt;
        to[++cnt]=u;
        nxt[cnt]=head[v];
        dd[cnt]=0;
        head[v]=cnt;
    }
    void build(int &x,int l,int r){
        x=++tot;
        if(l==r){
            return;
        }
        int mid=(l+r)/2;
        adde(tot+1,x,inf);
        build(ch[x][0],l,mid);
        adde(tot+1,x,inf);
        build(ch[x][1],mid+1,r);
    }
    void update(int y,int &x,int l,int r,int k,int node){
        x=++tot;
        ch[x][0]=ch[y][0];
        ch[x][1]=ch[y][1];
        adde(y,x,inf);
        if(l==r){
            adde(node,x,inf);
            return;
        }
        int mid=(l+r)/2;
        adde(tot+1,x,inf);
        if(k<=mid){
            update(ch[y][0],ch[x][0],l,mid,k,node);
        }else{
            update(ch[y][1],ch[x][1],mid+1,r,k,node);
        }
    }
    void get(int x,int l,int r,int L,int R,int nnode){
        if(L<=l&&R>=r){
            adde(x,nnode,inf);
            return;
        }
        int mid=(l+r)/2;
        if(L<=mid){
            get(ch[x][0],l,mid,L,R,nnode);
        }
        if(R>mid){
            get(ch[x][1],mid+1,r,L,R,nnode);
        }
    }
    bool bfs(){
        memset(dep,0,sizeof(int)*(tot+1));
        while(!q.empty()){
            q.pop();
        }
        dep[s]=1;
        q.push(s);
        while(!q.empty()){
            int u=q.front(),v;
            q.pop();
            for(int i=head[u];i;i=nxt[i]){
                v=to[i];
                if(dd[i]&&!dep[v]){
                    dep[v]=dep[u]+1;
                    if(v==t){
                        return true;
                    }
                    q.push(v);
                }
            }
        }
        return false;
    }
    ll dfs(int u,int f){
        if(u==t){
            return f;
        }
        int v;
        ll res=0,tmp;
        for(int &i=work[u];i&&f;i=nxt[i]){
            v=to[i];
            if(dd[i]&&dep[v]==dep[u]+1&&(tmp=dfs(v,min(f,dd[i])))){
                dd[i]-=tmp;
                dd[i^1]+=tmp;
                f-=tmp;
                res+=tmp;
            }
        }
        if(!res){
            dep[u]=0;
        }
        return res;
    }
    ll maxflow(){
        ll res=0;
        while(bfs()){
            memcpy(work,head,sizeof(int)*(tot+1));
            res+=dfs(s,0x7fffffff);
        }
        return res;
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            scanf("%d%d%d%d%d%d",&a[i],&b[i],&w[i],&l[i],&r[i],&p[i]);
            Hash[++Hash[0]]=a[i];
            ans+=b[i]+w[i];
        }
        Hash[++Hash[0]]=inf;
        sort(Hash+1,Hash+Hash[0]+1);
        Hash[0]=unique(Hash+1,Hash+Hash[0]+1)-Hash-1;
        for(int i=1;i<=n;i++){
            a[i]=lower_bound(Hash+1,Hash+Hash[0]+1,a[i])-Hash;
            l[i]=lower_bound(Hash+1,Hash+Hash[0]+1,l[i])-Hash;
            r[i]=upper_bound(Hash+1,Hash+Hash[0]+1,r[i])-Hash-1;
        }
        build(root[0],1,Hash[0]);
        for(int i=1;i<=n;i++){
            int node=++tot,nnode=++tot;
            adde(s,node,w[i]);
            adde(node,t,b[i]);
            adde(nnode,node,p[i]);
            update(root[i-1],root[i],1,Hash[0],a[i],node);
            if(l[i]<=r[i]){
                get(root[i-1],1,Hash[0],l[i],r[i],nnode);
            }
        }
        printf("%lld
    ",ans-maxflow());
        return 0;
    }
  • 相关阅读:
    asp数据查询及数据筛选
    数据链接(无源方式)
    HTML5 Input 类型
    PS调出米黄色复古柔和外景人物照
    PS调出清新淡雅外景女生背影照
    PS提亮户外儿童照
    PS制作恐怖逼真滴血文字
    ps昏暗室内照片调成暖色光亮效果
    PS滤镜制作下雨照片特效
    PS滤镜给城市夜空照片添加满天星
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476861.html
Copyright © 2011-2022 走看看