[UOJ217]奇怪的线段树
如果一个节点是$0$但它子树内有$1$那么无解,否则我们只需把那些是$1$但子树内没有其他$1$的节点(这些区间是被定位的区间)都访问一遍即可
根据ZKW线段树定位区间的过程,可以发现一段(从左到右)连续的右儿子+左儿子序列确定了一个区间
所以对每个右儿子$[l,r]$,连$[0,\infty)$向$[r+1,x]$的节点,对每个左儿子$[l,r]$,连$[0,+\infty)$向$[r+1,x]$的左儿子,再对那些被定位到的点拆点连$[1,\infty)$,跑最小流即可
但这样边数太多,考虑优化,建$n$个附加点,对于左儿子$[l,r]$,从附加点$l$连向它再连向附加点$r+1$,但这样会产生左儿子连到右儿子这种不合法情况,所以对左儿子和右儿子分别建$n$个附加点即可
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int inf=2147483647;
int h[24010],nex[128010],to[128010],cap[128010],M=1,S,T;
void ins(int a,int b,int c){
M++;
to[M]=b;
cap[M]=c;
nex[M]=h[a];
h[a]=M;
}
void add(int a,int b,int c){
ins(a,b,c);
ins(b,a,0);
}
int dis[24010],q[24010];
bool bfs(){
int head,tail,x,i;
memset(dis,-1,sizeof(dis));
head=tail=1;
q[1]=S;
dis[S]=0;
while(head<=tail){
x=q[head++];
for(i=h[x];i;i=nex[i]){
if(cap[i]&&dis[to[i]]==-1){
dis[to[i]]=dis[x]+1;
if(to[i]==T)return 1;
q[++tail]=to[i];
}
}
}
return 0;
}
int cur[24010];
int dfs(int x,int flow){
if(x==T)return flow;
int us=0,i,t;
for(i=cur[x];i&&flow;i=nex[i]){
if(cap[i]&&dis[to[i]]==dis[x]+1){
t=dfs(to[i],min(flow,cap[i]));
cap[i]-=t;
cap[i^1]+=t;
us+=t;
flow-=t;
if(cap[i])cur[x]=i;
}
}
if(us==0)dis[x]=-1;
return us;
}
int dicnic(){
int ans=0;
while(bfs()){
memcpy(cur,h,sizeof(h));
ans+=dfs(S,inf);
}
return ans;
}
void add(int a,int b,int l,int r){
if(l){
add(S,b,l);
add(a,T,l);
}
if(r!=inf)r-=l;
add(a,b,r);
}
int tS,tT;
int minflow(){
dicnic();
add(tT,tS,0,inf);
return dicnic();
}
int lp[4010],rp[4010],n,N;
int build(int l,int r,int f){
int siz=0,t,mid;
scanf("%d",&t);
if(l<r){
scanf("%d",&mid);
siz=build(l,mid,0)+build(mid+1,r,1);
}
if(!t&&siz)throw"OwO";
if(t){
add(tS,N,0,inf);
add(N,N+1,!siz,inf);
add(N+1,tT,0,inf);
if(f==1){
add(rp[l],N,0,inf);
if(r<n){
add(N+1,rp[r+1],0,inf);
add(N+1,lp[r+1],0,inf);
}
}
if(f==0){
add(rp[l],N,0,inf);
add(lp[l],N,0,inf);
if(r<n)add(N+1,lp[r+1],0,inf);
}
N+=2;
}
return siz+t;
}
int main(){
scanf("%d",&n);
try{
S=1;
T=2;
tS=3;
tT=4;
for(int i=1;i<=n;i++){
lp[i]=i+4;
rp[i]=i+n+4;
}
N=rp[n]+1;
build(1,n,-1);
printf("%d",minflow());
}catch(const char*s){
puts(s);
}
}
[UOJ217]奇怪的线段树的更多相关文章
- 「UNR#1」奇怪的线段树
「UNR#1」奇怪的线段树 一道好题,感觉解法非常自然. 首先我们只需要考虑一次染色最下面被包含的那些区间,因为把无解判掉以后只要染了一个节点,它的祖先也一定被染了.然后发现一次染色最下面的那些区间一 ...
- [UOJ UNR#1]奇怪的线段树
来自FallDream的博客,未经允许,请勿转载, 谢谢. 原题可以到UOJ看,传送门 如果存在一个点是白的,却有儿子是黑的,显然无解. 不然的话,只要所有黑色的“黑叶子”节点,即没有黑色的儿子的节点 ...
- UOJ 217 奇怪的线段树
http://uoj.ac/problem/217 题意就不X了,思路在这: 居然一开始把sap里面的mn设置为inf了,我是傻逼.. #include<cstdio> #include& ...
- [UOJ] #217. 【UNR #1】奇怪的线段树
题解见大佬博客 我的丑陋代码: #include<cstdio> #include<cstring> #include<cstdlib> inline int re ...
- 【vijos】1750 建房子(线段树套线段树+前缀和)
https://vijos.org/p/1750 是不是我想复杂了.... 自己yy了个二维线段树,然后愉快的敲打. 但是wa了两法.......sad 原因是在处理第二维的更新出现了个小问题,sad ...
- POJ2374 Fence Obstacle Course 【线段树】
题目链接 POJ2374 题解 题意: 给出\(n\)个平行于\(x\)轴的栅栏,求从一侧栅栏的某个位置出发,绕过所有栅栏到达另一侧\(x = 0\)位置的最短水平距离 往上说都是线段树优化dp 我写 ...
- B3038 上帝造题的七分钟2 线段树
这就是一道变得比较奇怪的线段树,维护每个区间的最大值和区间和,然后关键在于每次取根号的话数值下降的特别快,不用几次就都是1了,所以每次暴力单点修改,然后直接找区间最大值,假如区间最大值是1的话,就直接 ...
- 2018.07.25 bzoj3878: [Ahoi2014&Jsoi2014]奇怪的计算器(线段树)
传送门 线段树综合. 让我想起一道叫做siano" role="presentation" style="position: relative;"&g ...
- CF914D Bash and a Tough Math Puzzle 线段树+gcd??奇怪而精妙
嗯~~,好题... 用线段树维护区间gcd,按如下法则递归:(记题目中猜测的那个数为x,改动次数为tot) 1.若子区间的gcd是x的倍数,不递归: 2.若子区间的gcd是x的倍数,且没有递归到叶子结 ...
随机推荐
- z-index 不起作用
1.第一种情况(z-index无论设置多高都不起作用情况): 这种情况发生的条件有三个: 1.父标签 position属性为relative: 2.问题标签无position属性(不包括static) ...
- webpack自动生成项目的html
1 自动生成多个html页面 设置webpack.config.js中的plugins属性,多次调用plugin插件(new htmlWebpackPlugin()),同时设置对应数量的.js入口文件 ...
- c语言中的size_t
size_t unsigned int 类型,无符号,它的取值没有负数.用来表示 参数/数组元素个数,sizeof 返回值,或 str相关函数返回的 size 或 长度.sizeof 操作符的结果类型 ...
- System V共享内存介绍
(一)简单概念 共享内存作为一种进程间通信的方式,其相较于其他进程间通信方式而言最大的优点就是数据传输速率快.其内部实现的方式采用了Linux进程地址空间中的mmap文件映射区,将文件内容直接映射到各 ...
- python基础===python os.path模块
os.path.abspath(path) #返回绝对路径 os.path.basename(path) #返回文件名 os.path.commonprefix(list) #返回list(多个路径) ...
- centos 安装flash
linux系统中安装flash插件 linux中安装flashplayer插件的简单方法: 1.下载其中最新版本的播放器,下载地址: http://get.adobe.com/cn/flashplay ...
- 【模板】BZOJ 3781: 小B的询问 莫队算法
http://www.lydsy.com/JudgeOnline/problem.php?id=3781 N个数的序列,每次询问区间中每种数字出现次数的平方和,可以离线. 丢模板: #include ...
- HDU 6109 数据分割 并查集,SET
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6109 题意:中文题面 解法:每次都贪心地尝试将尽量多的条件放进当前这组,遇到第一个与已有条件冲突时,就 ...
- FineReport——发送邮件
在FR中,个用户之间可以通过邮件的形式进行通信,但是存在一个问题就是FineReport平台只能设置一个发件人账户,收件人账户可以有多个. 所以在实际的系统开发中可能需要自己开发信息交互的模块. 在系 ...
- oracle导入DMP步骤
oracle导入DMP步骤如下:1.已经存在的数据库需要进行以下的操作,如果不存在,可略过: 删除用户 drop user SUDMDB cascade; 删除表空间和数据文件 ...