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 ...
随机推荐
- Flex 4 自定义预加载器
本示例的目的是在Flash Professional里创建自定义预加载器SWC,并扩展SparkDownloadProgressBar类在Flex 4应用程序中使用. 预加载器显示加载进度百分比 ...
- 【Nginx】I/O多路转接之select、poll、epoll
当需要读两个以上的I/O的时候,如果使用阻塞式的I/O,那么可能长时间的阻塞在一个描述符上面,另外的描述符虽然有数据但是不能读出来,这样实时性不能满足要求,大概的解决方案有以下几种: 1.使用多进程或 ...
- DRBD+Heratbeat+NFS高可用文件共享存储
一.概述 .通过ha-log日志可以看出主释放资源,备接管资源. 来自为知笔记(Wiz)
- [LeetCode] Contains Duplicate(II,III)
Contains Duplicate Given an array of integers, find if the array contains any duplicates. Your funct ...
- Eclipse配置中文(汉化)
1.首先打开网址:http://www.eclipse.org/babel/downloads.php 然后查看安装以及版本选择 关于安装存储库,去这里查看 我选的是最新的版本:oxygen 未FQ请 ...
- 【Mongodb教程 第二课 】 MongoDB 创建数据库 use 命令
use 命令 MongoDB use DATABASE_NAME 用于创建数据库.该命令将创建一个新的数据库,如果它不存在,否则将返回现有的数据库. 语法: use DATABASE 语句的基本语法如 ...
- php验证邮箱
<?php if(isset($_POST['email'])){ $email = $_POST['email']; if(filter_var($email, FILTER_VALIDATE ...
- MongoDB 操作手冊CRUD 更新 update
改动记录 概述 MongoDB提供了update()方法用于更新记录. 这种方法接受下面參数: 一个更新条件的JSON对象用于匹配记录,一个更新操作JSON对象用于声明更新操作,和一个选项JS ...
- GCC 编译详解 (转)
GNU CC(简称为Gcc)是GNU项目中符合ANSI C标准的编译系统,能够编译用C.C++和Object C等语言编写的程序.Gcc不仅功能强大,而且可以编译如C.C++.Object C.Jav ...
- IO流-获取指定目录下文件夹和文件对象【File类】
一.运用File类实现获取指定目录下文件夹和文件对象 1.File类 2.方法: 获取文件绝对路径 :getAbsolutePath 案例: import java.io.File; /** * 获取 ...