bzoj 3218 a + b Problem(最小割+主席树)
【题目链接】
http://www.lydsy.com/JudgeOnline/problem.php?id=3218
【题意】
给n个格子涂白或黑色,白则wi,黑则bi的好看度,若黑格i存在:
1<=j<I,li<=aj<=ri,格子为白色
则损失pi,问最大的好看度。
【思路】
考虑建立最小割模型:
- 首先将一个点拆成两个中间连pi
- 连边(S,Xi,wi) (Xi,T,bi)
- 对于一个满足i要求的j,连边(Xj,Yi,inf),代表i只有两种选择,一为设白色,一为损失pi。
这样跑出的最小割即为答案。
但该图的边数过多,因此需要优化。
建一棵线段树,由线段树中所有被[li,ri]包含的点向Yi连边inf,由Xi向对应的叶子连边。然后加上j<i的条件,我们需要一棵可持久化线段树,因此需要Yi被T[i-1]的[li,ri]区间连边,Xi向T[i]的叶子连边。这样就成功将边数缩到O(nlogn)级别。
【代码】
1 #include<set> 2 #include<cmath> 3 #include<queue> 4 #include<vector> 5 #include<cstdio> 6 #include<cstring> 7 #include<iostream> 8 #include<algorithm> 9 #define X(i) (i) 10 #define Y(i) (i+n) 11 #define trav(u,i) for(int i=front[u];i;i=e[i].nxt) 12 #define FOR(a,b,c) for(int a=(b);a<=(c);a++) 13 using namespace std; 14 15 typedef long long ll; 16 const int N = 2e5+200; 17 const int inf = 1e9; 18 19 ll read() { 20 char c=getchar(); 21 ll f=1,x=0; 22 while(!isdigit(c)) { 23 if(c=='-') f=-1; c=getchar(); 24 } 25 while(isdigit(c)) 26 x=x*10+c-'0',c=getchar(); 27 return x*f; 28 } 29 30 struct Edge { 31 int u,v,cap,flow; 32 }; 33 struct Dinic { 34 int d[N],cur[N],vis[N]; 35 vector<Edge> es; 36 vector<int> g[N]; 37 queue<int> q; 38 39 void AddEdge (int u,int v,int w) { 40 es.push_back((Edge){u,v,w,0}); 41 es.push_back((Edge){v,u,0,0}); 42 int m=es.size(); 43 g[u].push_back(m-2); 44 g[v].push_back(m-1); 45 } 46 bool bfs(int s,int t) { 47 memset(vis,0,sizeof(vis)); 48 d[s]=0; vis[s]=1; 49 q.push(s); 50 while(!q.empty()) { 51 int u=q.front(); q.pop(); 52 FOR(i,0,(int)g[u].size()-1) { 53 Edge& e=es[g[u][i]]; 54 int v=e.v; 55 if(e.cap>e.flow&&!vis[v]) { 56 vis[v]=1; 57 d[v]=d[u]+1; 58 q.push(v); 59 } 60 } 61 } 62 return vis[t]; 63 } 64 int dfs(int u,int a,int t) { 65 if(u==t||a==0) return a; 66 int flow=0,f; 67 for(int& i=cur[u];i<g[u].size();i++) { 68 Edge& e=es[g[u][i]]; 69 int v=e.v; 70 if(d[v]==d[u]+1&&(f=dfs(v,min(a,e.cap-e.flow),t))>0) { 71 e.flow+=f; 72 es[g[u][i]^1].flow-=f; 73 flow+=f,a-=f; 74 if(!a) break; 75 } 76 } 77 return flow; 78 } 79 int maxflow(int s,int t) { 80 int flow=0; 81 while(bfs(s,t)) { 82 memset(cur,0,sizeof(cur)); 83 flow+=dfs(s,inf,t); 84 } 85 return flow; 86 } 87 } dc; 88 89 int n,cnt; 90 91 struct Tnode { 92 Tnode *ls,*rs; 93 int sum,id; 94 void * operator new (size_t,Tnode* l,Tnode* r) { 95 static Tnode mempool[N],*G=mempool; 96 G->ls=l,G->rs=r,G->id=++cnt; 97 return G++; 98 } 99 Tnode* build(int l,int r,int x,int from) { 100 int mid=l+r>>1; 101 Tnode *t; 102 if(l==r) 103 t=new (0x0,0x0)Tnode; 104 else if(x<=mid) 105 t=new (ls->build(l,mid,x,from),rs) Tnode; 106 else 107 t=new (ls,rs->build(mid+1,r,x,from)) Tnode; 108 dc.AddEdge(from,t->id,inf); 109 dc.AddEdge(id,t->id,inf); 110 return t; 111 } 112 void Add(int l,int r,int L,int R,int to) { 113 if(L<=l&&r<=R) { 114 dc.AddEdge(id,to,inf); 115 } else { 116 int mid=l+r>>1; 117 if(L<=mid&&ls) ls->Add(l,mid,L,R,to); 118 if(mid<R&&rs) rs->Add(mid+1,r,L,R,to); 119 } 120 } 121 122 } *T[5050]; 123 124 int hash[N],tot,a[N],b[N],l[N],r[N],p[N],w[N]; 125 126 int main() 127 { 128 n=read(); 129 cnt=Y(n); 130 int s=++cnt,t=++cnt; 131 T[0]=new (0x0,0x0)Tnode; 132 T[0]->ls=T[0]->rs=T[0]; 133 ll ans=0; 134 FOR(i,1,n) { 135 a[i]=read(),b[i]=read(),w[i]=read(),l[i]=read(),r[i]=read(),p[i]=read(); 136 hash[++tot]=a[i],hash[++tot]=l[i],hash[++tot]=r[i]; 137 } 138 139 sort(hash+1,hash+tot+1); 140 tot=unique(hash+1,hash+tot+1)-hash-1; 141 FOR(i,1,n) { 142 a[i]=lower_bound(hash+1,hash+tot+1,a[i])-hash; 143 l[i]=lower_bound(hash+1,hash+tot+1,l[i])-hash; 144 r[i]=lower_bound(hash+1,hash+tot+1,r[i])-hash; 145 } 146 147 FOR(i,1,n) { 148 ans+=w[i]+b[i]; 149 dc.AddEdge(s,X(i),w[i]); 150 dc.AddEdge(X(i),t,b[i]); 151 T[i]=T[i-1]->build(1,tot,a[i],X(i)); 152 T[i-1]->Add(1,tot,l[i],r[i],Y(i)); 153 dc.AddEdge(Y(i),X(i),p[i]); 154 } 155 ans-=dc.maxflow(s,t); 156 printf("%lld\n",ans); 157 return 0; 158 }
P.S.神的我无力吐槽=-=
posted on 2016-03-28 19:26 hahalidaxin 阅读(254) 评论(0) 编辑 收藏 举报