bzoj 2811: [Apio2012]Guard【线段树+贪心】
关于没有忍者的区间用线段树判就好啦
然后把剩下的区间改一改:l/r数组表示最左/最右没被删的点,然后删掉修改后的左边大于右边的;l升r降排个序,把包含完整区间的区间删掉;
然后设f/g数组表示i前/后的最少需要忍者数,这个贪心来转移即可,就是把忍者放在区间的最右/左位置
然后对于每个r判断。为什么是每个r而不是全部点,因为上一步的贪心。找到最右的r小于当前r-1的位置k1,最左的l大于当前r-1的位置k2,判断如果f[k1]+g[k2]+1>k,则说明此方案不合法,说明这个点必选
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int N=500005;
int n,k,m,tot,cnt,rl[N],l[N],r[N],con,f[N],g[N];
struct xds
{
int l,r,tg;
}t[N<<1];
struct qwe
{
int l,r,v;
qwe(int L=0,int R=0)
{
l=L,r=R;
}
}a[N],b[N];
bool cmp(const qwe &a,const qwe &b)
{
return a.l<b.l||(a.l==b.l&&a.r>b.r);
}
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
void build(int ro,int l,int r)
{
t[ro].l=l,t[ro].r=r;
if(l==r)
return;
int mid=(l+r)>>1;
build(ro<<1,l,mid);
build(ro<<1|1,mid+1,r);
}
void update(int ro,int l,int r)
{
if(t[ro].l==l&&t[ro].r==r)
{
t[ro].tg=1;
return;
}
int mid=(t[ro].l+t[ro].r)>>1;
if(r<=mid)
update(ro<<1,l,r);
else if(l>mid)
update(ro<<1|1,l,r);
else
{
update(ro<<1,l,mid);
update(ro<<1|1,mid+1,r);
}
}
int ques(int ro,int x)
{
if(t[ro].tg)
return t[ro].tg;
if(t[ro].l==t[ro].r)
return 0;
int mid=(t[ro].l+t[ro].r)>>1;
if(x<=mid)
return ques(ro<<1,x);
else
return ques(ro<<1|1,x);
}
int main()
{
n=read(),k=read(),m=read();
build(1,1,n);
for(int i=1;i<=m;i++)
{
int x=read(),y=read(),z=read();
if(!z)
update(1,x,y);
else
a[++tot]=qwe(x,y);
}
for(int i=1;i<=n;i++)
if(!ques(1,i))
l[i]=r[i]=++cnt,rl[cnt]=i;
if(cnt==k)
{
for(int i=1;i<=n;i++)
if(l[i])
printf("%d\n",i);
return 0;
}
for(int i=1;i<=n;i++)
if(!l[i])
l[i]=l[i-1];
r[n+1]=cnt+1;
for(int i=n;i>=1;i--)
if(!r[i])
r[i]=r[i+1];
for(int i=1;i<=tot;i++)
{
a[i].l=r[a[i].l],a[i].r=l[a[i].r];
if(a[i].l<=a[i].r)
a[++con]=a[i];
}
sort(a+1,a+1+con,cmp);
tot=0;
for(int i=1;i<=con;i++)
{
while(tot>=1&&b[tot].l<=a[i].l&&a[i].r<=b[tot].r)
tot--;
b[++tot]=a[i];
}
int mn=1e9,mx=0;
for(int i=1;i<=tot;i++)
{
if(b[i].l>mx)
f[i]=f[i-1]+1,mx=b[i].r;
else
f[i]=f[i-1];
}
for(int i=tot;i>=1;i--)
{
if(b[i].r<mn)
g[i]=g[i+1]+1,mn=b[i].l;
else
g[i]=g[i+1];
}
bool fl=0;
for(int i=1;i<=tot;i++)
{
if(f[i]!=f[i-1]+1)
continue;
if(b[i].l==b[i].r)
{
fl=1;
printf("%d\n",rl[b[i].l]);
continue;
}
int x=b[i].r-1,l=1,r=i-1,k1=0,k2=tot+1;
while(l<=r)
{
int mid=(l+r)>>1;
if(b[mid].r<x)
k1=mid,l=mid+1;
else
r=mid-1;
}
l=i+1,r=tot;
while(l<=r)
{
int mid=(l+r)>>1;
if(b[mid].l>x)
k2=mid,r=mid-1;
else
l=mid+1;
}
if(f[k1]+g[k2]+1>k)
fl=1,printf("%d\n",rl[b[i].r]);
}
if(!fl)
puts("-1");
return 0;
}
bzoj 2811: [Apio2012]Guard【线段树+贪心】的更多相关文章
- Bzoj5251 线段树+贪心
Bzoj5251 线段树+贪心 记录本蒟蒻省选后的第一篇题解!国际惯例的题面:首先这个东西显然是一棵树.如果我们把数值排序,并建立这棵树的dfs序,显然dfs序上的一个区间对应数值的一个区间,且根为数 ...
- BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心
BZOJ_1826_[JSOI2010]缓存交换 _线段树+贪心 Description 在计算机中,CPU只能和高速缓存Cache直接交换数据.当所需的内存单元不在Cache中时,则需要从主存里把数 ...
- 2018.10.20 NOIP模拟 蛋糕(线段树+贪心/lis)
传送门 听说是最长反链衍生出的对偶定理就能秒了. 本蒟蒻直接用线段树模拟维护的. 对于第一维排序. 维护第二维的偏序关系可以借助线段树/树状数组维护逆序对的思想建立权值线段树贪心求解. 代码
- Bzoj 2752 高速公路 (期望,线段树)
Bzoj 2752 高速公路 (期望,线段树) 题目链接 这道题显然求边,因为题目是一条链,所以直接采用把边编上号.看成序列即可 \(1\)与\(2\)号点的边连得是. 编号为\(1\)的点.查询的时 ...
- BZOJ2809&&LG1552 APIO2012派遣(线段树合并)
BZOJ2809&&LG1552 APIO2012派遣(线段树合并) 题面 自己找去 HINT 简化一题面就是让你从每个点的子树中以\(<=m\)的代价选取尽可能多的点,然后乘上 ...
- BZOJ 1577: [Usaco2009 Feb]庙会捷运Fair Shuttle 线段树 + 贪心
escription 公交车一共经过N(1<=N<=20000)个站点,从站点1一直驶到站点N.K(1<=K<=50000)群奶牛希望搭乘这辆公交车.第i群牛一共有Mi(1&l ...
- codeforces 675E Trains and Statistic 线段树+贪心统计
分析:这个题刚看起来无从下手 但是我们可以先简化问题,首先可以固定起点i,求出i+1到n的最小距离 它可以到达的范围是[i+1,a[i]],贪心的想,我们希望换一次车可以到达的距离尽量远 即:找一个k ...
- BZOJ.3938.Robot(李超线段树)
BZOJ UOJ 以时间\(t\)为横坐标,位置\(p\)为纵坐标建坐标系,那每个机器人就是一条\(0\sim INF\)的折线. 用李超线段树维护最大最小值.对于折线分成若干条线段依次插入即可. 最 ...
- BZOJ.1558.[JSOI2009]等差数列(线段树 差分)
BZOJ 洛谷 首先可以把原序列\(A_i\)转化成差分序列\(B_i\)去做. 这样对于区间加一个等差数列\((l,r,a_0,d)\),就可以转化为\(B_{l-1}\)+=\(a_0\),\(B ...
随机推荐
- oc温习二:基本运算及基本运算符
C语言一共有34种运算符,如下: 运算符分类: 1.按照功能划分: (1)算术运算符 + 加法运算符 - 减法运算符 或者负值运算符 * 乘法运算符 / 除法运算符 % 模运算符,或者取余运算符,要求 ...
- P1427 小鱼的数字游戏 洛谷
https://www.luogu.org/problem/show?pid=1427 题目描述 小鱼最近被要求参加一个数字游戏,要求它把看到的一串数字(长度不一定,以0结束,最多不超过100个,数字 ...
- c标准库函数 strcat
函数原型:extern char *strcat(char *dest,char *src) 参数说明:dest为一个目的字符串的指针,即被连接的字符串(在前),src为一个源字符串的指针(在后).所 ...
- Ubuntu 16.04安装Guake Terminal终端(使用一键唤醒功能)
安装: sudo apt-get install guake-indicator sudo apt-get install guake 使用: 先启动guake-indicator,再启动guake. ...
- mysql查询今天,昨天,近7天,近30天,本月,上一月数据的SQL
原文:http://www.open-open.com/code/view/1423207309170 select * from ad_proTrack_t where to_days(crt_ti ...
- HDU 1215.七夕节【筛选法】【7月26】
七夕节 七夕节那天,月老来到数字王国,他在城门上贴了一张告示,而且和数字王国的人们说:"你们想知道你们的还有一半是谁吗?那就依照告示上的方法去找吧!" 人们纷纷来到告示前,都想知道 ...
- 【转】海量数据处理算法-Bloom Filter
1. Bloom-Filter算法简介 Bloom Filter(BF)是一种空间效率很高的随机数据结构,它利用位数组很简洁地表示一个集合,并能判断一个元素是否属于这个集合.它是一个判断元素是否存在于 ...
- 【APUE】进程间通信之管道
管道是UNIX系统IPC最古老形式,并且所有UNIX系统都提供此种通信机制.管道由下面两种局限性: 1)历史上,它们是半双工的(即数据只能在一个方向上流动) 2)它们只能在具有公共祖先的进程之间使用. ...
- socket的bind函数是不是只能绑定本地IP,不能绑定外网IP么?
参考: https://bbs.csdn.net/topics/391024376 别瞎猜测. 所谓bind,就是指绑定本地接受端口. 指定ip,是为了分辨多ip主机. --------------- ...
- [NPM] npm check to update the dependencies
To update the dependencies in the project, we can run: npx npm-check -u