3218: a + b Problem
Time Limit: 20 Sec Memory Limit: 40 MB
Submit: 828 Solved: 289
[Submit][Status][Discuss]
这道题还是比较好的。
将点拆成i和i’。
从S向i连w[i]的边,从i向T连b[i]的边。
从i’向i连p[i]的边,从i之前符合条件的j向i’连inf的边。
这样的话边的大小是n^2的。
所以我们可以优化一下第四种边,可以用一颗权值线段树,连边是查询l[i],r[i]这段区间,从这段区间直接向i’连inf的边,再从i向a[i]所对应的叶子连inf的边。
但是这样的话就不能保证j < i了。所以需要将权值线段树变成主席树,每次新都新建出一条链来,再从对应的旧的链上的对应节点连过来就行了。
#include<cstdio>
using namespace std;
#include<iostream>
#include<algorithm>
#define T n*2+2
#define inf 0x7fffffff
const int N=100100;
const int M=1000000;
struct S{int st,en,va;}aa[M];
int l[M],r[M],root[M],siz=0;
int n,a[N],b[N],w[N],li[N],ri[N],p[N],ans,all[N*3];
int point[N],next[M],gap[N],dis[N],cur[N],pre[N],tot=1;
inline void add(int x,int y,int z){
next[++tot]=point[x];point[x]=tot;
aa[tot].st=x;aa[tot].en=y;aa[tot].va=z;
next[++tot]=point[y];point[y]=tot;
aa[tot].st=y;aa[tot].en=x;aa[tot].va=0;
}
inline int ISAP(int ss,int tt){
bool f;
int i,y,u,minn,sum=0;
u=ss;gap[0]=T+siz;
for(i=1;i<=T+siz;++i) cur[i]=point[i];
while(dis[ss]<T+siz){
f=false;
for(i=cur[u];i;i=next[i])
if(dis[aa[i].en]+1==dis[u]&&aa[i].va>0){
f=true;cur[u]=i;break;
}
if(f){
pre[u=aa[i].en]=i;
if(u==tt){
minn=inf;
for(i=u;i!=ss;i=aa[pre[i]].st)
minn=min(minn,aa[pre[i]].va);
for(i=u;i!=ss;i=aa[pre[i]].st){
aa[pre[i]].va-=minn;
aa[pre[i]^1].va+=minn;
}
u=ss;sum+=minn;
}
}
else{
--gap[dis[u]];
if(!gap[dis[u]]) return sum;
y=T+siz;cur[u]=point[u];
for(i=point[u];i;i=next[i])
if(aa[i].va>0) y=min(y,dis[aa[i].en]);
++gap[dis[u]=y+1];
if(u!=ss) u=aa[pre[u]].st;
}
}
return sum;
}
#define mid (L+R)/2
inline void insert(int L,int R,int x,int &y,int z,int to){
y=++siz;
add(to,y+T,inf);
add(x+T,y+T,inf);
if(L==R){
return ;
}
l[y]=l[x];r[y]=r[x];
if(z<=mid) insert(L,mid,l[x],l[y],z,to);
else insert(mid+1,R,r[x],r[y],z,to);
}
inline void query(int L,int R,int now,int x,int y,int to){
if (!now) return;
if(x<=L&&y>=R){
add(T+now,to,inf);
return ;
}
if(x<=mid) query(L,mid,l[now],x,y,to);
if(y>mid) query(mid+1,R,r[now],x,y,to);
}
int main(){
int i,j,size;
scanf("%d",&n);
for(i=1;i<=n;++i){
scanf("%d%d%d%d%d%d",&a[i],&b[i],&w[i],&li[i],&ri[i],&p[i]);
ans+=b[i]+w[i];
add(1,i+n+1,w[i]);
add(i+n+1,T,b[i]);
add(i+1,i+n+1,p[i]);
all[++all[0]]=a[i],all[++all[0]]=li[i],all[++all[0]]=ri[i];
}
sort(all+1,all+all[0]+1);
size=unique(all+1,all+all[0]+1)-all-1;
for(i=1;i<=n;++i){
a[i]=upper_bound(all+1,all+size+1,a[i])-all-1;
li[i]=upper_bound(all+1,all+size+1,li[i])-all-1;
ri[i]=upper_bound(all+1,all+size+1,ri[i])-all-1;
}
for(i=1;i<=n;++i){
insert(1,size,root[i-1],root[i],a[i],i+n+1);
query(1,size,root[i-1],li[i],ri[i],i+1);
}
printf("%d\n",ans-ISAP(1,T));
}