[COCI2017-2018#1] Deda

Description

  • 小马里卡正在创作一个奇妙的童话故事。她一边编故事,一边讲给她的爷爷听。爷爷可高兴了,于是问了她一些有趣的问题。
  • 在小马里卡的故事中,有N个年龄分别为1~N岁的孩子(最小的1为岁,最大的为N岁)。有一天,她们一起乘火车出去旅行。铁路线上有好多个车站,分别以0, 1, 2, 3……编号。其中第0站为始发站,火车每到一个车站都会停下来逗留一段时间。每个孩子都可以在选择自己喜欢的车站下车。
  • 小马里卡喜欢这样讲述她的故事:“在第X站,年龄为A岁的孩子下车了。”不过小马里卡的习惯非常不好,她讲述故事的顺序是完全随机的。换句话说,X是不单调的。爷爷知道小马里卡的坏习惯,所以他喜欢时不时问一些有趣的问题来找小马里的麻烦。问题是这样的:“年龄大于等于B且在第Y站(包含第Y站)以前下车的最年轻的小孩是多大?”
  • 小马里卡必须正确回答爷爷的问题,否则爷爷会因生气而睡觉。值得注意的是,小马里卡的答案必须在当时是正确的。虽然小马里卡在随后的讲述中可能会改变问题的答案,但这都是无关紧要的。
  • 小马里卡对自己的坏习惯十分无奈。由于故事的顺序过于杂乱,小马里卡根本无法正确回答爷爷的问题。于是她找到了聪明的你。请帮小马里卡编写一个程序,动态追踪她的讲述,并回答爷爷的问题。

Input

  • 输入的第一行包含两个正整数N,Q((2leqslant N,Qleqslant 200000)),分别代表孩子的数量和语句的数量。
  • 接下来Q行,每行一个语句。语句的格式为“M X A”或“D Y B”,分别代表小马里卡的讲述和爷爷的问题。其中M、D为大写字母,X、Y、A、B((1leqslant X,Yleqslant 1000000000,1leqslant A,Bleqslant 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


开始想到把车站离线离散化,然后每次查询(1sim y)区间内比(B)大的最小的年龄,结果发现完全无法查找。。。

然后改一下思路,直接用年龄作为下标建立线段树,线段树节点存储该年龄下车的站点,这样还可以避免多个人在同一站下车的情况

下车就是单点修改,查询的话,就在(Bsim 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
",ST.Query(1,1,n,y,n,x));
	}
	return 0;
}
原文地址:https://www.cnblogs.com/Wolfycz/p/13681959.html