zoukankan      html  css  js  c++  java
  • 「BZOJ 3218」 a + b Problem

    题目链接

    戳我

    (Solution)

    题目为什么是(a + b Problem)啊?这和题面半毛钱关系都没有。
    现在来讲一下这题的解法吧,我们首先看看没有奇怪的方格这一个条件吧.

    其实没有这个条件还是很简单的,就只要将每个点连向原点表示选流量为(B)表示选黑色的,在将这个点连向汇点流量为(W)表示选白色的,跑一遍最小割就好了

    现在来看看有奇怪的方格这一个条件吧,我们可以对于每个节点(i)新建一个节点(i'),我们将每个(i)连向(i')流量为(P),在对于满足奇怪方格限制的(j),将(i')(j)连一条流量为(inf)的边再跑最小割就好了

    但是这一题明显不是这么简单就好了,观察数据范围,发现这(n^2)的连边是过不去的.所以我们应该想想优化,至于怎么优化用一个主席树就好了.

    (Code)

    #include<bits/stdc++.h> 
    #define inf 1e9
    using namespace std;
    typedef long long ll;
    int read(){
        int x=0,f=1; char c=getchar();
        while(c<'0'||c>'9') f=(c=='-')?-1:1,c=getchar();
        while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();
        return x*f;
    }
    struct node{
        int to,next,v;
    }a[1000010];
    int head[500010],cnt,n,m,s,t,x,y,z,dep[85010];
    void add(int x,int y,int c){
        a[++cnt].to=y,a[cnt].next=head[x],a[cnt].v=c,head[x]=cnt;
    	a[++cnt].to=x,a[cnt].next=head[y],a[cnt].v=0,head[y]=cnt;
    }
    queue<int> q;
    int bfs(){
        memset(dep,0,sizeof(dep));
        q.push(s),dep[s]=1;
        while(!q.empty()){
            int now=q.front();
            q.pop();
            for(int i=head[now];i;i=a[i].next){
                int v=a[i].to;
    			if(!dep[v]&&a[i].v>0)
                    dep[v]=dep[now]+1,q.push(v);
            }
        }
        if(dep[t])
            return 1;
        return 0;
    }
    int dfs(int k,int list){
        if(k==t||!list)
            return list;
        for(int i=head[k];i;i=a[i].next){
            int v=a[i].to;
            if(dep[v]==dep[k]+1&&a[i].v>0){
                int p=dfs(v,min(list,a[i].v));
                if(p){
                    a[i].v-=p;
                    if(i&1) a[i+1].v+=p;
                    else a[i-1].v+=p;
                    return p;
                }
            }
        }
    	dep[k]=0;
        return 0;
    }
    int Dinic(){
        int ans=0,k;
        while(bfs()){
            while((k=dfs(s,inf)))
                ans+=k;
    	}
        return ans;
    }
    struct node1{
        int l,r;
    }tree[1000010];
    int tot,goal;
    void update(int &k,int f,int l,int r,int c){
    	k=++tot;
    	tree[k]=tree[f];
        if(l==r){
    		add(k+t,goal,inf);
    		if(f) add(k+t,f+t,inf);
    		return ;
    	}
        int mid=(l+r)>>1;
        if(c<=mid) update(tree[k].l,tree[f].l,l,mid,c);
        else update(tree[k].r,tree[f].r,mid+1,r,c);
    	if(tree[k].l) add(k+t,tree[k].l+t,inf);
    	if(tree[k].r) add(k+t,tree[k].r+t,inf);
    }
    void insert(int k,int l,int r,int L,int R) {
        if(L>r||l>R) return;
        if(L<=l&&r<=R) {
    		add(n+goal,t+k,inf);
    		return;
    	}
        int mid=(l+r)>>1;
        if(tree[k].l) insert(tree[k].l, l, mid, L,R);
        if(tree[k].r) insert(tree[k].r, mid+1,r,L,R);
    }
    int A[5011],B,W,L[5011],R[5011],P,sum,o[100010];
    int len,rt,p;
    main(){
        n=read(),s=0,t=n*2+1;
    	for(int i=1;i<=n;i++){
    		A[i]=read(),B=read(),W=read(),L[i]=read(),R[i]=read(),P=read(),sum+=B+W;
    		add(s,i,B),add(i,t,W),add(i,i+n,P),o[++len]=A[i],o[++len]=L[i],o[++len]=R[i];
    	}
        sort(o+1,o+len+1);
    	len=unique(o+1,o+len+1)-o-1;
        for (int i=1;i<=n;++i){
    		goal=i;
            A[i]=lower_bound(o+1,o+len+1,A[i])-o;
            L[i]=lower_bound(o+1,o+len+1,L[i])-o;
            R[i]=lower_bound(o+1,o+len+1,R[i])-o;
    		insert(p,1,len,L[i],R[i]);
    		update(rt,p,1,len,A[i]);
    		p=rt;
        }
        printf("%d
    ",sum-Dinic());
    }
    
  • 相关阅读:
    新文章new图标
    3.6SiteFactory专业版,顶部导航的最后一个栏目向下移位的解决办法
    http://goodboy5264.blog.163.com/
    提升你网站水平的 jQuery 插件推荐
    如何把导航条做成sitefactory政府版的样子实现动态读取子栏目显示
    好的链接
    2011年度最佳jQuery插件
    asp中日期时间函数介绍
    若干设计模式学习
    多线程学习
  • 原文地址:https://www.cnblogs.com/hbxblog/p/10308870.html
Copyright © 2011-2022 走看看