山东济南彤昌机械科技有限公司 山东济南江鹏工贸游有限公司

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,问最大的好看度。

 

【思路】

 

    考虑建立最小割模型:

  1. 首先将一个点拆成两个中间连pi
  2. 连边(S,Xi,wi) (Xi,T,bi)
  3. 对于一个满足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  阅读(239)  评论(0编辑  收藏  举报