众所周知,能用线段树做的题一定可以暴力

但考场上也只能想到暴力了,毕竟还是对线段树不熟练。

deda

描述

有一辆车上有n个小孩,年龄为1~n,然后q个询问,M X A代表在第X站时年龄为A的小孩会下车,D Y B代表询问年龄大于等于B且在第Y站(包含第Y站)以前下车的年龄最小的小孩,如果不存在,则输出-1。

.

输入

输入的第一行包含正整数N和Q,孩子的数量和询问的数量。

接下来Q行,每行3个值,第一个值为M或者D,询问有两种分别用M和D表示,M表示下车操作,D表示询问

如果是M X A,那么三个值的含义是:M X A代表在第X站时年龄为A的小孩会下车

如果是D Y B,代表询问年龄大于等于B且在第Y站(包含第Y站)以前下车的年龄最小的小孩,如果不存在,则输出-1。

所有询问都对应着不同的孩子,输入中至少有一行是询问的问题。

.

输出

对于每个询问的问题,输出答案。如果没有答案,输出-1。

.

分数分布

对于100%的数据:2≤N,Q≤200000,1≤X,Y≤1,000,000,000,1≤A,B≤N。

.

样例输入1

3 4

M 10 3

M 5 1

D 20 2

D 5 1

.

样例输出1

3

1

.

样例输入2

10 10

M 20 10

D 1 9

M 2 3

D 17 10

M 20 2

D 8 2

M 40 1

D 25 2

M 33 9

D 37 9

样例输出2

-1

-1

3

2

9

先来说说我的暴力做法吧(虽然这个做法只能40分,而且写出来有点蠢)

这道题我的第一反应是离线做,将每个询问的坐标从小到大排序依次处理,这样就可以保证"\(X<Y\)"这个条件了。

然而正解却直接用的是线段树。。。

根据数据范围,线段树表示的区间不能是坐标(因为1≤X,Y≤1,000,000,000)。所以我们可以用L-R来表示年龄为L岁到R岁的小孩中,他们下车的位置,坐标最小的那一个。

为什么是坐标最小的那一个呢,因为在询问中,

D Y B代表询问年龄大于等于B且在第Y站(包含第Y站)以前下车的年龄最小的小孩

既然要在第\(Y\)站之前,那么存进最小的位置肯定不会错。在查询时,我们只需要判断在当前区间\(L-R\)中,它的最小位置X是否小于\(Y\),如果是小于,我们继续,如果是大于,则return掉。

详情请见代码(线段树这种东西,不看代码是懂不了的)

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std; #define N 200010 int n,m,minv[N*10],x,age,ql,qr,ans=N+10;
char a; void Insert(int i,int L,int R) { //插入操作
if(L==R) {minv[i]=x; return ; }
int mid=(L+R)/2;
if(age<=mid) Insert(i*2,L,mid);
else Insert(i*2+1,mid+1,R);
minv[i]=min(minv[i*2],minv[i*2+1]);
} int Find(int i,int L,int R) {
if(minv[i]>x) return N+10;
if(L==R) return L; //L-R表示的年龄,所以要返回这个答案
int mid=(L+R)/2;
if(minv[i*2] <= x ) return Find(i*2,L,mid);
else return Find(i*2+1,mid+1,R);
} void Query(int i,int L,int R) {
if(ql<=L && qr>=R) {ans=Find(i,L,R); return ;} //找到符合条件的区间
int mid=(L+R)/2;
if(mid>=ql) {Query(i*2,L,mid); if(ans!=N+10) return ;}//如果找到了答案,那么
if(qr>mid) Query(i*2+1,mid+1,R); //(mid+1)-R的区间里的答案只会更大
} //所以return 掉 int main() {
memset(minv,0x3f,sizeof(minv));
cin>>n>>m;qr=n;
for(int i=1;i<=m;i++) {
cin>>a>>x>>age;
if(a=='M') Insert(1,1,n);
else { ql=age; Query(1,1,n); if(ans==N+10) cout<<"-1"<<endl; else cout<<ans<<endl; }
ans=N+10;
}
}

这道题的难点我认为是将l-r区间表示为年龄l-r的小朋友。

因为在平常线段树中,我们是在节点中存的答案,而这道题的做法却不一样。所以线段树是一个十分灵活的数据结构。

最新文章

  1. linkedin开源的kafka-monitor安装文档
  2. ubuntu中安装VMWare tools
  3. 用 get 同步/异步 方式获取网络数据并输出
  4. pentaho saiku 安装全过程
  5. 《Data-Intensive Text Processing with mapReduce》读书笔记之二:mapreduce编程、框架及运行
  6. [翻译]ASP.NET Web API 2入门
  7. css实现3D切换功能
  8. 解析JSON 注意解析数据为一个对象的情况.--加一下说明
  9. Django2.0 path和re_path使用
  10. redis安装以及php扩展
  11. 【Jmeter测试】接口请求完成后,查询数据库结果,检测数据存储是否正确
  12. php设计模式-工厂设计模式
  13. demo02
  14. javascript之url转义escape()、encodeURI()和decodeURI(),ifram父子传参参数有中文时出现乱码
  15. C# string 常用方法
  16. Hortonwork Ambari配置Hive集成Hbase的java开发maven配置
  17. spring线程池ThreadPoolTaskExecutor与阻塞队列BlockingQueue
  18. 使用websploit在局域网全自动渗透
  19. Redis(RedisTemplate)使用hash哈希
  20. 三次握手 四次握手 与socket函数的关系

热门文章

  1. APMServ升级PHP至5.3
  2. 模板 - 可持久化无旋Treap
  3. Angular ngTemplateOutlet
  4. C#设计模式:迭代器模式(Iterator Pattern)
  5. 使用vee-validate表单验证插件如何设置中文提示
  6. more - 在显示器上阅读文件的过滤器
  7. LightOJ 1289 LCM from 1 to n(位图标记+素数筛
  8. java四种引用类型以及使用场景详解
  9. SSM三大框架整合梳理
  10. The list of list is modified unexpected, python