关于没有忍者的区间用线段树判就好啦

然后把剩下的区间改一改: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;
}

最新文章

  1. CSS3:linear-gradient,线性渐变的使用方法
  2. jquery.mobile手机网页简要
  3. 惠普披甲过VR寒冬,花费巨资开发VR游戏
  4. 《JavaScript高级程序设计》读书笔记--(1)JavaScript简介
  5. 谈谈Java的集合组件
  6. android学习笔记四
  7. 转(HP大中华区总裁孙振耀退休感言)
  8. 06-OC分类、协议、ARC
  9. ROS机器人程序设计(原书第2版)补充资料 (贰) 第二章 ROS系统架构及概念
  10. LeetCode算法题-Linked List Cycle(Java实现)
  11. C#中存储数据的集合:数组、集合、泛型、字典
  12. ROS 时间同步问题
  13. C++11模版元编程的应用
  14. CF161D Distance in Tree(点分治)
  15. shell脚本实例-判断主机存活 以及企业备份方案
  16. .Net中使用ODP.net访问Oracle数据库
  17. SharpDX之Direct2D教程I——简单示例和Color(颜色)
  18. 多项式函数插值:多项式形式函数求值的Horner嵌套算法
  19. 关于pthread_cond_wait使用while循环判断的理解
  20. New Concept English Two 20 52

热门文章

  1. 前端学习之-- Jquery
  2. HDU 6441 费马大定理+勾股数
  3. [Bzoj3668][Noi2014]起床困难综合症(位运算)
  4. Date日期模式
  5. win10 笔记本猎豹WiFi无法打开
  6. @Aspect注解无效
  7. jquery显示和隐藏元素
  8. maven打包时的三方包的选择顺序
  9. vue + vue-lazyload 实现图片懒加载
  10. jQuery选择器特殊字符与属性空格问题