[COCI2017-2018#1] Deda
Description
- 小马里卡正在创作一个奇妙的童话故事。她一边编故事,一边讲给她的爷爷听。爷爷可高兴了,于是问了她一些有趣的问题。
- 在小马里卡的故事中,有N个年龄分别为1~N岁的孩子(最小的1为岁,最大的为N岁)。有一天,她们一起乘火车出去旅行。铁路线上有好多个车站,分别以0, 1, 2, 3……编号。其中第0站为始发站,火车每到一个车站都会停下来逗留一段时间。每个孩子都可以在选择自己喜欢的车站下车。
- 小马里卡喜欢这样讲述她的故事:“在第X站,年龄为A岁的孩子下车了。”不过小马里卡的习惯非常不好,她讲述故事的顺序是完全随机的。换句话说,X是不单调的。爷爷知道小马里卡的坏习惯,所以他喜欢时不时问一些有趣的问题来找小马里的麻烦。问题是这样的:“年龄大于等于B且在第Y站(包含第Y站)以前下车的最年轻的小孩是多大?”
- 小马里卡必须正确回答爷爷的问题,否则爷爷会因生气而睡觉。值得注意的是,小马里卡的答案必须在当时是正确的。虽然小马里卡在随后的讲述中可能会改变问题的答案,但这都是无关紧要的。
- 小马里卡对自己的坏习惯十分无奈。由于故事的顺序过于杂乱,小马里卡根本无法正确回答爷爷的问题。于是她找到了聪明的你。请帮小马里卡编写一个程序,动态追踪她的讲述,并回答爷爷的问题。
Input
- 输入的第一行包含两个正整数N,Q\((2\leqslant N,Q\leqslant 200000)\),分别代表孩子的数量和语句的数量。
- 接下来Q行,每行一个语句。语句的格式为“M X A”或“D Y B”,分别代表小马里卡的讲述和爷爷的问题。其中M、D为大写字母,X、Y、A、B\((1\leqslant X,Y\leqslant 1000000000,1\leqslant A,B\leqslant N)\)分别为一个正整数。其意义请见Description。题目中保证至少有一个“D”。
Output
对于每一个问题D输出一个答案。答案为一个整数。如果爷爷的问题无解,请输出-1。
Sample Input 1
3 4
M 10 3
M 5 1
D 20 2
D 5 1
Sample Output 1
3
1
Sample Input 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
Sample Output 2
-1
-1
3
2
9
开始想到把车站离线离散化,然后每次查询\(1\sim y\)区间内比\(B\)大的最小的年龄,结果发现完全无法查找。。。
然后改一下思路,直接用年龄作为下标建立线段树,线段树节点存储该年龄下车的站点,这样还可以避免多个人在同一站下车的情况
下车就是单点修改,查询的话,就在\(B\sim n\)年龄区间内找到一个满足条件的最小年龄。寻找的时候,如果区间内站点最小值比\(y\)大,就可以直接退出;同样,在查询时,如果左区间找到了答案,右区间也就不需要继续下去了。
具体实现可以看看代码
/*program from Wolfycz*/
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define inf 0x7f7f7f7f
//using namespace std;
typedef long long ll;
typedef unsigned int ui;
typedef unsigned long long ull;
inline char gc(){
static char buf[1000000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,1000000,stdin),p1==p2)?EOF:*p1++;
}
template<typename T>inline T frd(T x){
int f=1; char ch=gc();
for (;ch<'0'||ch>'9';ch=gc()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=gc()) x=(x<<1)+(x<<3)+ch-'0';
return x*f;
}
template<typename T>inline T read(T x){
int f=1;char ch=getchar();
for (;ch<'0'||ch>'9';ch=getchar()) if (ch=='-') f=-1;
for (;ch>='0'&&ch<='9';ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
return x*f;
}
inline void print(int x){
if (x<0) putchar('-'),x=-x;
if (x>9) print(x/10);
putchar(x%10+'0');
}
template<typename T>inline T min(T x,T y){return x<y?x:y;}
template<typename T>inline T max(T x,T y){return x>y?x:y;}
template<typename T>inline T Swap(T &x,T &y){T t=x; x=y,y=t;}
const int N=2e5;
struct S1{
#define ls (p<<1)
#define rs (p<<1|1)
int tree[N*4+10];
S1(){memset(tree,127,sizeof(tree));}
void Modify(int p,int l,int r,int x,int v){
if (l==r){
tree[p]=v;
return;
}
int mid=(l+r)>>1;
x<=mid?Modify(ls,l,mid,x,v):Modify(rs,mid+1,r,x,v);
tree[p]=min(tree[ls],tree[rs]);
}
int Query(int p,int l,int r,int L,int R,int x){
if (L<=l&&r<=R&&tree[p]>x) return -1;
if (l==r) return l;
int mid=(l+r)>>1,Ans=-1;
if (L<=mid) Ans=Query(ls,l,mid,L,R,x);
if (R>mid&&Ans==-1) Ans=Query(rs,mid+1,r,L,R,x);
return Ans;
}
#undef ls
#undef rs
}ST;//Segment Tree
int main(){
int n=read(0),m=read(0);
for (int i=1;i<=m;i++){
char ch[5]; scanf("%s",ch);
int x=read(0),y=read(0);
if (ch[0]=='M') ST.Modify(1,1,n,y,x);
else printf("%d\n",ST.Query(1,1,n,y,n,x));
}
return 0;
}