Solution

  看一下如何建最小割模型:

  先求$sum=\sum b_i+w_i$。

  如果某一个格子$i$选择了黑色,那么贡献是$-w_i$;如果满足是它奇怪的格子,还有额外贡献$-p_i$。

  如果选择了白色,那么贡献是$-b_i$。

  总贡献加上$sum$就是答案。

  对于如上条件,可以对每一个格子建立一个单元:

  可以发现,如果选择白色,那么直接割去$b[i]$这条边。那么要怎么影响之后的黑格呢?

  对于每一个点$i$,对于所有的$j>i$,使得$i$按题目要求可以使$j$成为奇怪的格子,那么由$i$向$j'$连一条$\infty$的边。

  如果第$i$个格子选择白色,那么对$j$的单元来说,必须割掉$p[j]$这条边,加上原本一定要割的$w[j]$,就是$j$成为奇怪格子的贡献。 

  由此建模完成。

  但是边数高达$O(n^2)$

  看看题目的要求是$i<j$,也就是说对于格子$i$,在$1...i-1$的范围内找权值为$[l_i,r_i]$的格子,对单元进行连接。

  看起来好像主席树啊,那就关于$a_i$建权值主席树吧。

  类似线段树优化网络流建边地,往主席树插入第$i$个格子的时候,将$i$(单元里面的那个$i$点)连向新链上每一个新节点,再由原节点连向新节点,流量都是$\infty$。

  注意不能像平时用线段树跑网络流一样在叶子底部连接,然后从儿子往父亲流。因为这样会出现版本的冲突。

  跑一下就好了。

  PS:边的计数器忘记初始化调了整整一个上午服了。。。

  


#include <cstdio>
#include <algorithm>
#include <queue>
using namespace std;
const int N=5010,NS=100010,INF=2147000000;
int n,a[N],b[N],w[N],lb[N],rb[N],p[N],sum;
int h[NS],tot,cnt,root[N];
int list[NS],ltot,maxs;
int ch[NS][2];
int S,T,dis[NS],cur[NS];
queue<int> q;
struct Edge{int v,f,next;}g[1000010];
inline void addEdge(int u,int v,int f){g[++tot].v=v; g[tot].f=f; g[tot].next=h[u]; h[u]=tot;g[++tot].v=u; g[tot].f=0; g[tot].next=h[v]; h[v]=tot;
}
void lsh(){sort(list+1,list+1+ltot);ltot=unique(list+1,list+1+ltot)-list-1;maxs=ltot;for(int i=1;i<=n;i++){a[i]=lower_bound(list+1,list+1+ltot,a[i])-list;lb[i]=lower_bound(list+1,list+1+ltot,lb[i])-list;rb[i]=lower_bound(list+1,list+1+ltot,rb[i])-list;}
}
int copy(int u){int v=++cnt;ch[v][0]=ch[u][0]; ch[v][1]=ch[u][1];if(u)addEdge(u,v,INF);return v;
}
void insert(int u,int &v,int l,int r,int pos,int who){v=copy(u);        addEdge(who*2-1,v,INF);if(l==r) return;int mid=(l+r)>>1;if(pos<=mid)insert(ch[u][0],ch[v][0],l,mid,pos,who);elseinsert(ch[u][1],ch[v][1],mid+1,r,pos,who);
}
void link(int u,int l,int r,int L,int R,int node){if(!u) return;if(L<=l&&r<=R){addEdge(u,node,INF);return;}int mid=(l+r)>>1;if(R<=mid) link(ch[u][0],l,mid,L,R,node);else if(mid<L) link(ch[u][1],mid+1,r,L,R,node);else{link(ch[u][0],l,mid,L,mid,node);link(ch[u][1],mid+1,r,mid+1,R,node);}
}
bool bfs(){while(!q.empty()) q.pop();q.push(S);for(int i=1;i<=cnt;i++) dis[i]=-1;dis[S]=0;while(!q.empty()){int u=q.front(); q.pop();for(int i=h[u],v;i;i=g[i].next)if(g[i].f&&dis[v=g[i].v]==-1){dis[v]=dis[u]+1;if(v==T) return true;q.push(v);}}return dis[T]!=-1;
}
int dfs(int u,int delta){if(u==T) return delta;int ret=0,get;for(int i=cur[u],v;i&&delta;i=g[i].next)if(g[i].f&&dis[v=g[i].v]==dis[u]+1){get=dfs(v,min(delta,g[i].f));g[i].f-=get;g[i^1].f+=get;if(g[i].f) cur[u]=i;delta-=get;ret+=get;}if(!ret) dis[u]=-1;return ret;
}
int dinic(){int ret=0;while(bfs()){for(int i=1;i<=cnt;i++) cur[i]=h[i];ret+=dfs(S,INF);}return ret;
}
int main(){scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d%d%d%d%d%d",&a[i],&b[i],&w[i],&lb[i],&rb[i],&p[i]);list[++ltot]=a[i];list[++ltot]=lb[i];list[++ltot]=rb[i];sum+=b[i]+w[i];}lsh();S=n*2+1; T=n*2+2;tot=1;for(int i=1;i<=n;i++){cnt+=2;addEdge(cnt,cnt-1,p[i]);addEdge(S,cnt-1,w[i]);addEdge(cnt-1,T,b[i]);}cnt+=2;for(int i=1;i<=n;i++)insert(root[i-1],root[i],1,maxs,a[i],i);    for(int i=2;i<=n;i++)link(root[i-1],1,maxs,lb[i],rb[i],i*2);int get=dinic();printf("%d\n",sum-get);return 0;
}

奇妙代码

转载于:https://www.cnblogs.com/RogerDTZ/p/8016382.html

【BZOJ3218】 a+b Problem相关推荐

  1. 【BZOJ3218】a+b problem (最小割 + 主席树)

    传送门 继续优化:把a[ ]离散化 #include<bits/stdc++.h> using namespace std; const int inf=1000000007; const ...

  2. 洛谷 P1919 【模板】A*B Problem升级版(FFT快速傅里叶)

    题目链接:P1919 [模板]A*B Problem升级版(FFT快速傅里叶) 题意 给定两个 \(n\) 位 \(10\) 进制整数 \(x\) 和 \(y\),求 \(x*y\). 思路 FFT ...

  3. 洛谷 P1919 【模板】A*B Problem升级版 【快速傅里叶变换 FFT】

    [洛谷 P1919] [模板]A*B Problem升级版 题目大意 给你两个超大整数 a,ba,ba,b,问 a∗ba*ba∗b 其中 a,b≤101000000a,b\leq10^{1000000 ...

  4. [P1919 【模板】A*B Problem升级版(FFT快速傅里叶)(高精乘板子,FFT板子)

    P1919 [模板]A*B Problem升级版(FFT快速傅里叶) 分析: ​ 为什么高精乘可以用 FFT 优化??? ​ 众所周知 FFT 是解决多项式之间的乘法运算,将乘数的每一位看成多项式的系 ...

  5. 【Git】SSL certificate problem: unable to get local issuer certificate错误的解决办法

    问题描述 unable to access 'https://*****.git/': SSL certificate problem: unable to get local issuer cert ...

  6. 【HDOJ】1022 Train Problem I_天涯浪子_新浪博客

    [题目]http://acm.hdu.edu.cn/showproblem.php?pid=1022 [报告] 模拟,直接模拟一个栈的运行就行了. [程序] // Task: 1022 Train P ...

  7. 【HDOJ】1023 Train Problem II_天涯浪子_新浪博客

    [题目]http://acm.hdu.edu.cn/showproblem.php?pid=1023 [报告] 简单粗暴的卡特兰数,不过要用大数才能过呦~ [程序] // Task: 1023 Tra ...

  8. 【模板】A*B Problem升级版(FFT快速傅里叶)

    总算是弄懂了一点点FFTFFTFFT 但是那个蝴蝶操作还只是背的板子呜呜 先放个优化高精度乘法的板子在这里把 P3803 [模板]多项式乘法(FFT) #include <cmath> # ...

  9. 【UVA】11991 Easy Problem from Rujia Liu? (整数v第k次出现在什么位置)

    https://vjudge.net/problem/UVA-11991 题目大意:就是给你一个序列,然后给出k和v,看整数v第k次出现在该序列的什么位置,没有的话就输出0 结构体(略复杂): #in ...

  10. 【BZOJ】3339: Rmq Problem 3585: mex(线段树+特殊的技巧)

    http://www.lydsy.com/JudgeOnline/problem.php?id=3585 好神的题. 但是!!!!!!!!!!!!!!我线段树现在要开8倍空间才能过!!!!!!!!!! ...

最新文章

  1. 【Kali渗透全方位实战】子域名的概念与探测(DNSenum工具和Sublist3r脚本的使用)
  2. 基于R语言的梯度推进算法介绍
  3. python对csv文件中的数据进行分类_利用Python对csv文件中的数据进行排序
  4. Replace Type Code with Subclasses(以子类取代类型码)
  5. c语言数组最大可定义多少位_C语言求数组的最大值三种方法
  6. sed 分隔符打印_字符截取:cut,格式化输出:printf,字符截取:awk,文件或命令输出编辑:sed...
  7. Javascript ES6 Set、Map、Proxy、Symbol
  8. 西安电子科技计算机专业,2020西安电子科技大学计算机专业课改考
  9. 由儿时的游戏打保猜最广想到的
  10. linux下载dvwa教程,Dvwa安装,配置(Linux)
  11. gRPC调试, 用 Apipost
  12. java 正数转负数函数_Java数学函数将正整数转换为负数并将负整数转换为正数?...
  13. linux的xshell怎么保存密码,Xshell保存账号密码方法
  14. NKOJ——P1095——气球游戏
  15. 【 C++ 】红黑树
  16. 好几张图片合成一个PDF,不能错过的小技巧!
  17. 漏洞复现-OpenSSL
  18. PHP - 设计模式系列
  19. 什么是pinterest
  20. 大叔学编程,学的还是易语言

热门文章

  1. 游戏开发论坛_微信小游戏增速35% 重度游戏最高单款累计流水8亿 | 游戏茶馆
  2. 2018-08-20nosql(memcached)笔记
  3. 根据数据库名称glkf查看使用的用户
  4. 安卓微信视频播放全屏问题处理
  5. RAID磁盘阵列的部署(red hat 6.5)
  6. VisualGDB系列9:配置VS直接通过SSH方式访问Linux项目
  7. unity3d所要知道的基础知识体系大纲,可以对照着学习
  8. Bootstrap 3.2.0 源码试读 2014/08/14
  9. [Iphone开发]如何在GDB中查看变量的值
  10. 【TDA4系列】Linux SDK安装与交叉编译测试,以及刷写SD卡