【BZOJ 3218】 3218: a + b Problem(最小割+可持久化线段树)

 

 

3218: a + b Problem

Time Limit: 20 Sec  Memory Limit: 40 MB
Submit: 1440  Solved: 545

Description

Input

Output

Sample Input

Sample Output

HINT

Source

 

 

【分析】

  这题建图很神哦!

  其实只是边的合并。

  就是说,原本海陆型建图就好了的。

  

  但是这样有一点问题,就是pj只算一次的,但是这样跑算了很多次。

  改一改图。

  

  这样就好了。

  但是边很多。

  一开始没注意那个l~r的,就觉得嗯,开一些辅助点合并一下边。

  后来发现还有l~r的限制,其实也是开一些辅助点合并一下边,但是这里就有点高级了。

  就是值考虑l<=a<=r的话就是开个权值线段树然后用线段树上的点作为辅助点。

  但是还有一个条件是i<=j的时候才算,所以是可持久化线段树。

  关于辅助点,其实上面的j‘就是辅助点,照着做就好了。

 

  1 #include<cstdio>
  2 #include<cstdlib>
  3 #include<cstring>
  4 #include<iostream>
  5 #include<algorithm>
  6 #include<queue>
  7 using namespace std;
  8 #define Maxn 5010
  9 #define Maxm 1000000000
 10 // #define Maxm 10
 11 #define INF 0x7fffffff
 12 // #define LL long long
 13 
 14 int mymin(int x,int y) {return x<y?x:y;}
 15 
 16 struct node
 17 {
 18     int x,y,f,o,next;
 19 }t[Maxn*210];
 20 int len,first[Maxn*40];
 21 
 22 void ins(int x,int y,int f)
 23 {
 24     if(y==0) return;
 25     t[++len].x=x;t[len].y=y;t[len].f=f;
 26     t[len].next=first[x];first[x]=len;t[len].o=len+1;
 27     t[++len].x=y;t[len].y=x;t[len].f=0;
 28     t[len].next=first[y];first[y]=len;t[len].o=len-1;
 29 }
 30 
 31 int dis[Maxn*40],st,ed;
 32 queue<int > q;
 33 bool bfs()
 34 {
 35     memset(dis,-1,sizeof(dis));
 36     while(!q.empty()) q.pop();
 37     dis[st]=0;q.push(st);
 38     while(!q.empty())
 39     {
 40         int x=q.front();
 41         for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
 42         {
 43             int y=t[i].y;
 44             if(dis[y]==-1)
 45             {
 46                 dis[y]=dis[x]+1;
 47                 q.push(y);
 48             }
 49         }
 50         q.pop();
 51     }
 52     if(dis[ed]==-1) return 0;
 53     return 1;
 54 }
 55 
 56 int ffind(int x,int flow)
 57 {
 58     if(x==ed) return flow;
 59     int now=0;
 60     for(int i=first[x];i;i=t[i].next) if(t[i].f>0)
 61     {
 62         int y=t[i].y;
 63         if(dis[y]==dis[x]+1)
 64         {
 65             int a=ffind(y,mymin(flow-now,t[i].f));
 66             t[i].f-=a;
 67             t[t[i].o].f+=a;
 68             now+=a;
 69         }
 70         if(now==flow) break;
 71     }
 72     if(now==0) dis[x]=-1;
 73     return now;
 74 }
 75 
 76 int ans=0;
 77 void max_flow()
 78 {
 79     while(bfs())
 80     {
 81         ans-=ffind(st,INF);
 82     }
 83 }
 84 void output()
 85 {
 86     for(int i=1;i<=len;i+=2)
 87     {
 88         printf("%d -> %d %d\n",t[i].x,t[i].y,t[i].f);
 89     }printf("\n");
 90 }
 91 
 92 int rt[Maxn],cnt;
 93 struct nnode
 94 {
 95     int lc,rc;
 96 }tr[Maxn*40];
 97 
 98 
 99 void add(int l,int r,int x,int y,int a,int id)
100 {
101     ins(y,x,INF);
102     ins(y,id,INF);
103     if(l==r) return;
104     int mid=(l+r)>>1;
105     if(a<=mid)
106     {
107         tr[y].lc=++cnt;tr[y].rc=tr[x].rc;
108         add(l,mid,tr[x].lc,tr[y].lc,a,id);
109     }
110     else
111     {
112         tr[y].rc=++cnt;tr[y].lc=tr[x].lc;
113         add(mid+1,r,tr[x].rc,tr[y].rc,a,id);
114     }
115 }
116 
117 void add2(int l,int r,int x,int al,int ar,int id)
118 {
119     if(l==al&&r==ar)
120     {
121         ins(id,x,INF);
122         return;
123     }
124     int mid=(l+r)>>1;
125     if(ar<=mid) add2(l,mid,tr[x].lc,al,ar,id);
126     else if(al>mid) add2(mid+1,r,tr[x].rc,al,ar,id);
127     else
128     {
129         add2(l,mid,tr[x].lc,al,mid,id);
130         add2(mid+1,r,tr[x].rc,mid+1,ar,id);
131     }
132 }
133 
134 
135 int main()
136 {
137     int n;
138     scanf("%d",&n);
139     st=n*2+1,ed=st+1;cnt=ed;
140     rt[0]=0;
141     len=0;
142     memset(first,0,sizeof(first));
143     for(int i=1;i<=n;i++)
144     {
145         int a,b,c,w,al,ar,p;
146         scanf("%d%d%d%d%d%d",&a,&b,&w,&al,&ar,&p);
147         ans+=b+w;
148         ins(st,i,b);ins(i,ed,w);
149         ins(i,i+n,p);
150         rt[i]=++cnt;
151         add(0,Maxm,rt[i-1],rt[i],a,i);
152         add2(0,Maxm,rt[i],al,ar,i+n);
153     }
154     // output();
155     max_flow();
156     printf("%d\n",ans);
157     return 0;
158 }
View Code

 

2017-04-06 22:05:14

 

转载于:https://www.cnblogs.com/Konjakmoyu/p/6675690.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值