题解

网络流优化建图经典题

现在才来写。。。(希望为时不晚)

 

开始正解

首先,我们可以想到一个正常(暴力)的建图方法

(图中红色的边i'->x存在当且仅当 x满足li<=ax<=ri)

明显暴力建图会T,5000*5000*5000*5000

 

于是我们有个想法,把所有a权值相邻的点放到一起来连边,用一个父亲节点来管辖它们这样就可以避免每个点i'都要单独连边向x,可以勉强联想到线段树的区间查询

又因为有一个j<i的条件,所有就建一棵主席树就可以了

我们把每个i点排序后依次插入到的对应位置(最好离散化一下)

边插入边查询,查询就是连边建图(主席树上跑网络流)

最后的边数大概是5000*log5000

 

虽然时间复杂度还是不对,但是网络流的复杂度毕竟玄学

代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
using namespace std;
#define N 200005
#define M 1000005
const int INF=0x3f3f3f3f;
int fir[N],nxt[M],to[M],cap[M],cnt;
struct node{int l,r;}a[N];
struct anode{int a,b,w,l,r,p;}b[5005];
int hh[15005],len;
int tot,RT[5005],n;
int S,T,flow,d[N];
queue<int> q;

void adde(int a,int b,int c)
{
	to[++cnt]=b;nxt[cnt]=fir[a];fir[a]=cnt;cap[cnt]=c;
	to[++cnt]=a;nxt[cnt]=fir[b];fir[b]=cnt;cap[cnt]=0;
}
bool bfs()
{
	memset(d,0x3f,sizeof(d));
	q.push(T);d[T]=0;
	int u,v,p;
	while(!q.empty()){
		u=q.front();q.pop();
		for(p=fir[u];p;p=nxt[p])
			if(cap[p^1]>0&&d[v=to[p]]==INF)
				q.push(v),d[v]=d[u]+1;
	}
	return d[S]!=INF;
}
int dinic(int u,int aug)
{
	if(u==T) return aug;
	int ret=0,tmp;
	for(int v,p=fir[u];p;p=nxt[p]){
		if(cap[p]>0&&d[u]==d[v=to[p]]+1){
			tmp=dinic(v,min(aug,cap[p]));
			aug-=tmp;cap[p]-=tmp;
			ret+=tmp;cap[p^1]+=tmp;
			if(!aug) break;
		}
	}
	return ret;
}
void f(){flow=0;while(bfs())flow+=dinic(S,INF);}

void insert(int &rt,int prt,int l,int r,int k)
{
	rt=++tot;
	if(l==r){
		adde(T+rt,k,INF);
		if(prt) adde(T+rt,T+prt,INF);
		return;
	}
	int mid=(l+r)>>1;
	if(b[k].a<=mid) a[rt].r=a[prt].r,insert(a[rt].l,a[prt].l,l,mid,k);
	else a[rt].l=a[prt].l,insert(a[rt].r,a[prt].r,mid+1,r,k);
	if(a[rt].l) adde(T+rt,T+a[rt].l,INF);
	if(a[rt].r) adde(T+rt,T+a[rt].r,INF);
}
void query(int rt,int l,int r,int k)
{
	if(!rt) return;
	if(b[k].l<=l&&r<=b[k].r){adde(k+n,T+rt,INF);return;}
	int mid=(l+r)>>1;
	if(b[k].l<=mid) query(a[rt].l,l,mid,k);
	if(b[k].r>mid) query(a[rt].r,mid+1,r,k);
}
int main()
{
	cnt=1;tot=0;
	long long ans=0;int i;
	scanf("%d",&n);S=2*n+1;T=2*n+2;
	for(i=1;i<=n;i++){
		scanf("%d%d%d%d%d%d",&b[i].a,&b[i].b,&b[i].w,&b[i].l,&b[i].r,&b[i].p);
		hh[3*i-2]=b[i].a;hh[3*i-1]=b[i].l;hh[3*i]=b[i].r;ans+=1ll*b[i].b+1ll*b[i].w;
		adde(S,i,b[i].b);adde(i,T,b[i].w);adde(i,i+n,b[i].p);
	}
	sort(hh+1,hh+3*n+1);int len=unique(hh+1,hh+3*n+1)-hh-1;
	for(i=1;i<=n;i++){
		b[i].a=lower_bound(hh+1,hh+len+1,b[i].a)-hh;
		b[i].l=lower_bound(hh+1,hh+len+1,b[i].l)-hh;
		b[i].r=lower_bound(hh+1,hh+len+1,b[i].r)-hh;
	}
	for(i=1;i<=n;i++){
		if(i>1)query(RT[i-1],1,len,i);
		insert(RT[i],RT[i-1],1,len,i);
	}
	f();printf("%lld",ans-flow);
}