• [UOJ#77]A+B Problem


    可持久化线段树优化连边。。。
    发现连线段树优化连边都没有在正式比赛考过。。。
    网络流建模
    问题转化成(sum (Bi+Wi) -sum_{黑点}Wi-sum_{白点}Bi-sum_{奇怪的点}Pi)
    S->i连一条容量为Bi的边,表示选白色,i->T连条容量为Wi的边,i->i'连容量Pi的边,i'->会因它变得奇怪的点 连inf,当i为白色时,如果对应点选黑色,一定花Pi才能割开。
    求最小割即可。因为强制j<i因此强行可持久化。。。

    #include <iostream>
    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    #include <queue>
    using namespace std;
    const int N=300005,inf=2100000000;
    struct Edge{int to,nxt,val;}e[N*10];
    int ls[N],rs[N],val[N],sum[N],a[5005],b[5005],w[5005],l[5005],r[5005],p[5005],n,tmp,c[5005*3],ans,head[N],ecnt=1,tot,cur[N],S,T;
    void ins(int bg,int ed,int val) {
        e[++ecnt].to=ed;
        e[ecnt].nxt=head[bg];
        e[ecnt].val=val;
        head[bg]=ecnt;
    }
    void add(int a,int b,int c) {
    	ins(a,b,c);ins(b,a,0);
    }
    void ins(int k,int l,int r,int ql,int qr,int id) {
    	if(!k) return;
    	int mid=l+r>>1;
    	if(ql<=l&&r<=qr) {add(id,k,inf);return;}
    	if(ql<=mid) ins(ls[k],l,mid,ql,qr,id);
    	if(mid+1<=qr) ins(rs[k],mid+1,r,ql,qr,id);
    }
    void update(int &k,int l,int r,int val,int id) {
    	ls[++tot]=ls[k],rs[tot]=rs[k];
    	int mid=l+r>>1;
    	if(l==r) {
    		if(k) add(tot,k,inf);
    		add(tot,id,inf);
    		k=tot;return;
    	}
    	k=tot;
    	if(val<=mid) update(ls[k],l,mid,val,id);
    	else update(rs[k],mid+1,r,val,id);
    }
    
    int h[N];
    queue<int>q;
    bool bfs() {
        memset(h,-1,sizeof h);
        q.push(S);
        h[S]=0;
        while(!q.empty()) {
            int x=q.front();
            q.pop();
            for(int i=head[x]; i; i=e[i].nxt) {
                if(e[i].val&&h[e[i].to]==-1) {
                    h[e[i].to]=h[x]+1;
                    q.push(e[i].to);
                }
            }
        }
        return h[T]!=-1;
    }
    int dfs(int x,int f) {
        if(x==T)return f;
        int tp,used=0;
        for(int i=cur[x]; i; i=e[i].nxt) {
            if(e[i].val&&h[e[i].to]==h[x]+1) {
                tp=dfs(e[i].to,min(e[i].val,f-used));
                e[i].val-=tp;
                if(e[i].val)cur[x]=i;
                e[i^1].val+=tp;
                used+=tp;
                if(used==f)return f;
            }
        }
        if(!used)h[x]=-1;
        return used;
    }
    void dinic() {
        while(bfs()) {
            memcpy(cur,head,sizeof head);
            ans-=dfs(S,inf);
        }
    }
    int main() {
    	scanf("%d",&n);S=n+n+1,T=n+n+2;
    	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]),
    	c[++tmp]=a[i],c[++tmp]=l[i],c[++tmp]=r[i],ans+=b[i]+w[i];
    	sort(c+1,c+1+tmp);
    	int u=unique(c+1,c+1+tmp)-c-1;
    	for(int i=1;i<=n;i++) {
    		add(S,i,b[i]),add(i,T,w[i]),add(i,i+n,p[i]);
    		a[i]=lower_bound(c+1,c+1+u,a[i])-c;
    		l[i]=lower_bound(c+1,c+1+u,l[i])-c;
    		r[i]=lower_bound(c+1,c+1+u,r[i])-c;
    	}
    	tot=n+n+2;
    	for(int i=1,rt=0;i<=n;i++) {
    		ins(rt,1,u,l[i],r[i],i+n);
    		update(rt,1,u,a[i],i);
    	}
    	for(int i=n+n+3;i<=tot;i++) {
    		if(ls[i]) add(i,ls[i],inf);
    		if(rs[i]) add(i,rs[i],inf);
    	}
    	dinic();
    	cout<<ans;
    }	
    
    我是咸鱼。转载博客请征得博主同意Orz
  • 相关阅读:
    Tempter of the Bone 搜索---奇偶性剪枝
    uestc 1709 Binary Operations 位运算的灵活运用
    uestc 1072 a ^ b
    uestc Another LCIS
    武汉邀请赛 Key Logger 双向链表
    bnu 29378 Adidas vs Adivon 基础题
    中南月赛F ZZY and his little friends
    日期问题
    开灯问题
    开灯问题
  • 原文地址:https://www.cnblogs.com/sdfzhsz/p/9493514.html
Copyright © 2020-2023  润新知