zoukankan      html  css  js  c++  java
  • [BZOJ3218]a + b Problem

    bzoj

    description


    sol

    最小鸽建图。
    假设(S)集合是染黑色,(T)集合是染白色。
    那么从(S)(i)(b_i)边,从(i)(T)(w_i)边。
    每个点(i)多拆出一个点(i'),从(i)(i')(p_i)边。对于所有满足(1le j<i)(l_ile a_jle r_i)(j),从(i')(j)(inf)边。
    然后跑最小鸽就好了。

    然鹅。这样建图的边数是(O(n^2))级别的。
    所以肯定是过不去的。
    考虑优化。
    发现条件其实是一个二位偏序的形式,所以可以用主席树优化建边。
    具体来说,以(a)值作为主席树下标,每个(i')向主席树上的(log n)个区间连边,每个区间向其中包含的所有(i)连边,容量都是(inf)
    这样点数和边数都是(O(nlog n))级别的,就可以通过本题了。

    code

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    int gi(){
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    const int N = 5e5+5;
    const int inf = 1e9;
    struct president_tree{int ls,rs;}t[N<<2];
    struct edge{int to,nxt,w;}a[N];
    int n,A[N],l[N],r[N],o[N],len,S,T,tot,head[N],cnt=1,dep[N],cur[N],rt,goal,ans;
    queue<int>Q;
    void link(int u,int v,int w){
    	a[++cnt]=(edge){v,head[u],w};head[u]=cnt;
    	a[++cnt]=(edge){u,head[v],0};head[v]=cnt;
    }
    bool bfs(){
    	memset(dep,0,sizeof(dep));
    	dep[S]=1;Q.push(S);
    	while (!Q.empty()){
    		int u=Q.front();Q.pop();
    		for (int e=head[u];e;e=a[e].nxt)
    			if (a[e].w&&!dep[a[e].to])
    				dep[a[e].to]=dep[u]+1,Q.push(a[e].to);
    	}
    	return dep[T];
    }
    int dfs(int u,int f){
    	if (u==T) return f;
    	for (int &e=cur[u];e;e=a[e].nxt)
    		if (a[e].w&&dep[a[e].to]==dep[u]+1){
    			int tmp=dfs(a[e].to,min(a[e].w,f));
    			if (tmp) {a[e].w-=tmp;a[e^1].w+=tmp;return tmp;}
    		}
    	return 0;
    }
    int dinic(){
    	int res=0;
    	while (bfs()){
    		for (int i=1;i<=tot;++i) cur[i]=head[i];
    		while (int tmp=dfs(S,inf)) res+=tmp;
    	}
    	return res;
    }
    void query(int x,int l,int r,int ql,int qr){
    	if (l>=ql&&r<=qr) {link(goal,x,inf);return;}
    	int mid=l+r>>1;
    	if (ql<=mid) query(t[x].ls,l,mid,ql,qr);
    	if (qr>mid) query(t[x].rs,mid+1,r,ql,qr);
    }
    void modify(int &x,int l,int r,int p){
    	t[++tot]=t[x];link(tot,x,inf);x=tot;
    	link(x,goal,inf);
    	if (l==r) return;int mid=l+r>>1;
    	if (p<=mid) modify(t[x].ls,l,mid,p);else modify(t[x].rs,mid+1,r,p);
    }
    int main(){
    	n=gi();S=2*n+1;T=tot=2*n+2;
    	for (int i=1,b,w,p;i<=n;++i){
    		A[i]=gi(),b=gi(),w=gi(),ans+=b+w;
    		l[i]=gi(),r[i]=gi(),p=gi();
    		link(S,i,b),link(i,T,w);
    		link(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){
    		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;
    		goal=n+i,query(rt,1,len,l[i],r[i]);
    		goal=i,modify(rt,1,len,A[i]);
    	}
    	printf("%d
    ",ans-dinic());
    	return 0;
    }
    
  • 相关阅读:
    python列表[]中括号
    python元组()小括号
    python break continue跳过和跳出循环
    python FOR循环
    python while循环
    python if elif else判断语句
    python使用变量
    python -input用户输入
    pycharm模板
    港股收费
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/9139559.html
Copyright © 2011-2022 走看看