bzoj3218 a + b Problem
Description
Input
Output
Sample Input
10
0 1 7 3 9 2
7 4 0 9 10 5
1 0 4 2 10 2
7 9 1 5 7 2
6 3 5 3 6 2
6 6 4 1 8 1
6 1 6 0 6 5
2 2 5 0 9 3
5 1 3 0 2 5
5 6 7 1 1 2
0 1 7 3 9 2
7 4 0 9 10 5
1 0 4 2 10 2
7 9 1 5 7 2
6 3 5 3 6 2
6 6 4 1 8 1
6 1 6 0 6 5
2 2 5 0 9 3
5 1 3 0 2 5
5 6 7 1 1 2
Sample Output
55
正解:最小割+主席树优化连边。
考虑拆点。$S$向$i$连$w$边,$i$向$T$连$b$边,$i'$向$i$连$p$边。如果$j$能使$i$变成奇怪的方格,那么$j$向$i'$连$inf$的边。
我们发现这样求出最小割就是答案,然而建图是$O(n^{2})$的,我们用主席树优化连边就行了。
每次新建一个版本,历史版本的结点向当前点连边,同时当前的$i$向主席树中经过的每一个点连边。
我们查询路径时,把整个区间抠出来,然后对应的线段树结点向$i$连边就行了。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 #define inf (1<<30) 14 #define N (500010) 15 #define il inline 16 #define RG register 17 #define ll long long 18 19 using namespace std; 20 21 struct edge{ int nt,to,flow,cap; }g[1000010]; 22 23 int head[N],cur[N],d[N],q[N],a[N],l[N],r[N],n,num=1; 24 int ls[N],rs[N],rt[N],hsh[N],sz,S,T,tot,ans,goal; 25 26 il int gi(){ 27 RG int x=0,q=1; RG char ch=getchar(); 28 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 29 if (ch=='-') q=-1,ch=getchar(); 30 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 31 return q*x; 32 } 33 34 il void insert(RG int from,RG int to,RG int cap){ 35 g[++num]=(edge){head[from],to,0,cap},head[from]=num; return; 36 } 37 38 il int bfs(RG int S,RG int T){ 39 memset(d,0,sizeof(d)),d[S]=1; 40 RG int h=0,t=1; q[t]=S; 41 while (h<t){ 42 RG int x=q[++h],v; 43 for (RG int i=head[x];i;i=g[i].nt){ 44 v=g[i].to; 45 if (!d[v] && g[i].cap>g[i].flow){ 46 d[v]=d[x]+1,q[++t]=v; 47 if (v==T) return 1; 48 } 49 } 50 } 51 return d[T]; 52 } 53 54 il int dfs(RG int x,RG int T,RG int a){ 55 if (!a || x==T) return a; RG int flow=0,f,v; 56 for (RG int &i=cur[x];i;i=g[i].nt){ 57 v=g[i].to; 58 if (d[v]==d[x]+1 && g[i].cap>g[i].flow){ 59 f=dfs(v,T,min(a,g[i].cap-g[i].flow)); 60 if (!f){ d[v]=0; continue; } 61 g[i].flow+=f,g[i^1].flow-=f; 62 flow+=f,a-=f; if (!a) return flow; 63 } 64 } 65 return flow; 66 } 67 68 il int maxflow(RG int S,RG int T){ 69 RG int flow=0; 70 while (bfs(S,T)){ 71 memcpy(cur,head,sizeof(head)); 72 flow+=dfs(S,T,inf); 73 } 74 return flow; 75 } 76 77 il void build(RG int x,RG int &y,RG int l,RG int r,RG int p){ 78 y=++sz,ls[y]=ls[x],rs[y]=rs[x]; 79 insert(x,y,inf),insert(y,x,0); 80 insert(goal,y,inf),insert(y,goal,0); 81 if (l==r) return; RG int mid=(l+r)>>1; 82 p<=mid ? build(ls[x],ls[y],l,mid,p) : build(rs[x],rs[y],mid+1,r,p); 83 return; 84 } 85 86 il void query(RG int x,RG int l,RG int r,RG int xl,RG int xr){ 87 if (xl<=l && r<=xr){ insert(x,goal,inf),insert(goal,x,0); return; } 88 RG int mid=(l+r)>>1; 89 if (xr<=mid) query(ls[x],l,mid,xl,xr); 90 else if (xl>mid) query(rs[x],mid+1,r,xl,xr); 91 else query(ls[x],l,mid,xl,mid),query(rs[x],mid+1,r,mid+1,xr); 92 return; 93 } 94 95 int main(){ 96 #ifndef ONLINE_JUDGE 97 freopen("a+b.in","r",stdin); 98 freopen("a+b.out","w",stdout); 99 #endif 100 n=gi(),S=2*n+1,T=2*n+2,sz=T; 101 for (RG int i=1,b,w,p;i<=n;++i){ 102 a[i]=gi(),b=gi(),w=gi(),ans+=b+w; 103 l[i]=gi(),r[i]=gi(),p=gi(); 104 insert(S,i,w),insert(i,S,0); 105 insert(i,T,b),insert(T,i,0); 106 insert(n+i,i,p),insert(i,n+i,0); 107 hsh[++tot]=a[i],hsh[++tot]=l[i],hsh[++tot]=r[i]; 108 } 109 sort(hsh+1,hsh+tot+1),tot=unique(hsh+1,hsh+tot+1)-hsh-1; 110 for (RG int i=1;i<=n;++i){ 111 a[i]=lower_bound(hsh+1,hsh+tot+1,a[i])-hsh; 112 l[i]=lower_bound(hsh+1,hsh+tot+1,l[i])-hsh; 113 r[i]=lower_bound(hsh+1,hsh+tot+1,r[i])-hsh; 114 goal=n+i,query(rt[i-1],1,tot,l[i],r[i]); 115 goal=i,build(rt[i-1],rt[i],1,tot,a[i]); 116 } 117 printf("%d\n",ans-maxflow(S,T)); 118 return 0; 119 }