BZOJ3218 A+B problem

题目传送门

分析:

首先把公式换一下。。。

ans=sigma(i<=n){w[i]+b[i]} - sigma(i为白色){b[i]} -sigma(i为黑色){w[i]} - sigma(i奇怪){p[i]}

然后我们就需要后面那一块最小。。。

非黑即白是一对矛盾关系,奇怪的点也是一个矛盾关系

于是考虑最小割

首先每个点分别向S和T连边,容量分别是b[i]与w[i]

然后每个点 i 复制出一个 i' 连容量为p[i]的边

i' 再向所有矛盾的 j 连边,容量INF

demo,边数好像会炸

然后发现非法的 j 是区间

然后就线段树连边

编号还要比 i 小。。。

那就只有主席树了

这么强行地把主席树和网络流联系起来吗,无力吐槽2333

8是很懂,这个范围能过。。。

 

  1 #include
  2 #include
  3 #include
  4 #include
  5 #include
  6 #include
  7 #include
  8   
  9 #define maxn 5005
 10 #define maxm 1000005
 11 #define INF 0x3f3f3f3f
 12 #define opst(i) (((i-1)^1)+1)
 13  
 14 using namespace std;
 15   
 16 inline int getint()
 17 {
 18     int num=0,flag=1;char c;
 19     while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
 20     while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
 21     return num*flag;
 22 }
 23  
 24 int n,S,T,N;
 25 int fir[maxn*20],nxt[maxm],to[maxm],cap[maxm],cnt;
 26 int h[20*maxn];
 27 int A[maxn],L[maxn],R[maxn],B[maxn],W[maxn],P[maxn],Q[3*maxn];
 28 struct node{int lc,rc;}t[maxn*20];
 29 int rt[maxn],tot;
 30 int ans,maxflow;
 31  
 32 inline void newnode(int u,int v,int w)
 33 {to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt,cap[cnt]=w;}
 34 inline void Add(int u,int v,int w)
 35 {newnode(u,v,w),newnode(v,u,0);}
 36  
 37 inline int find(int num)
 38 {
 39     int l=1,r=N;
 40     while(l<r)
 41     {
 42         int mid=(l+r)>>1;
 43         if(Q[mid]>=num)r=mid;
 44         else l=mid+1;
 45     }
 46     return l;
 47 }
 48  
 49 inline void Link(int now,int l,int r,int i)
 50 {
 51     if(R[i]r)return;
 52     if(L[i]<=l&&r<=R[i]){Add(i+n,T+now,INF);return;}
 53     int mid=(l+r)>>1;
 54     if(t[now].lc)Link(t[now].lc,l,mid,i);
 55     if(t[now].rc)Link(t[now].rc,mid+1,r,i);
 56 }
 57  
 58 inline void insert(int &now,int pre,int l,int r,int i)
 59 {
 60     if(!now||now==pre)now=++tot,t[now]=t[pre];
 61     if(l==r){Add(T+now,i,INF);if(pre)Add(T+now,T+pre,INF);return;}
 62     int mid=(l+r)>>1;
 63     if(A[i]<=mid)insert(t[now].lc,t[pre].lc,l,mid,i);
 64     else insert(t[now].rc,t[pre].rc,mid+1,r,i);
 65     if(t[now].lc)Add(T+now,T+t[now].lc,INF);
 66     if(t[now].rc)Add(T+now,T+t[now].rc,INF);
 67 }
 68  
 69 inline bool bfs()
 70 {
 71     memset(h,-1,sizeof h);h[S]=0;
 72     queue<int>Q;Q.push(S);
 73     while(!Q.empty())
 74     {
 75         int u=Q.front();Q.pop();
 76         for(int i=fir[u];i;i=nxt[i])
 77             if(cap[i]&&!~h[to[i]])
 78                 h[to[i]]=h[u]+1,Q.push(to[i]);
 79     }
 80     return ~h[T];
 81 }
 82  
 83 inline int dfs(int u,int flow)
 84 {
 85     int used=0;
 86     if(u==T)return flow;
 87     for(int i=fir[u];i;i=nxt[i])
 88         if(cap[i]&&h[to[i]]==h[u]+1)
 89         {
 90             int w=flow-used;
 91             w=dfs(to[i],min(w,cap[i]));
 92             cap[i]-=w,cap[opst(i)]+=w,used+=w;
 93             if(used==flow)return flow;
 94         }
 95     if(!used)h[u]=-1;
 96     return used;
 97 }
 98  
 99 inline void dinic()
100 {while(bfs())maxflow+=dfs(S,INF);}
101  
102 int main()
103 {
104     n=getint();
105     for(int i=1;i<=n;i++)
106     {
107         A[i]=getint(),ans+=B[i]=getint(),ans+=W[i]=getint();
108         L[i]=getint(),R[i]=getint(),P[i]=getint();
109         Q[++N]=A[i],Q[++N]=L[i],Q[++N]=R[i];
110     }
111     sort(Q+1,Q+N+1),N=unique(Q+1,Q+N+1)-(Q+1);
112     T=2*n+1;
113     for(int i=1;i<=n;i++)
114     {
115         A[i]=find(A[i]);
116         L[i]=find(L[i]);
117         R[i]=find(R[i]);
118         Add(S,i,B[i]),Add(i,T,W[i]),Add(i,i+n,P[i]);
119     }
120     for(int i=1;i<=n;i++)
121     {
122         if(i>1)Link(rt[i-1],1,N,i);
123         insert(rt[i],rt[i-1],1,N,i);
124     }
125     dinic();
126     printf("%d\n",ans-maxflow);
127 }
View Code

 

你可能感兴趣的:(BZOJ3218 A+B problem)