这题嘛,一拿到手,我第一反应是线段树套平衡树……然后就被ZH大佬D了:“这题不是排个序加平衡树就好了吗?”
QAQ,大佬就是大佬,一针见血的解决了题目。然后JYZ来问:“这一定是一道很难的题目吧?”“不会啊,一道傻逼模板题罢了。”ZH大佬淡淡的说。
(JYZ大佬只是在装弱罢了,他太强了,不过一个大佬%比他弱的人是要降RP的)
这题的题目中明确指出:每个区间不互相包含。
因此我们可以把所有的询问排个序,然后维护一棵平衡树,平衡树内的所有节点为当前询问区间内的所有狗狗的漂亮值。
在区间转换时,只需要删去前面多余的节点,增加后面需要的节点,维护平衡树就行了。
附上AC代码:
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <cstdlib>
#define N 300010
using namespace std;
struct note{
int x,y,w,wz;
bool operator < (const note lyf) const {
if (x==lyf.x) return y<lyf.y;
return x<lyf.x;
}
}a[50010];
struct tree{
int w,g,size,rnd;
}t[N];
int n,m,w[N],size,l,r,rt,son[N][2],ans[50010];
inline char nc(){
static char ch[100010],*p1=ch,*p2=ch;
return p1==p2&&(p2=(p1=ch)+fread(ch,1,100010,stdin),p1==p2)?EOF:*p1++;
}
inline void read(int &a){
static char c=nc();int f=1;
for (;!isdigit(c);c=nc()) if (c=='-') f=-1;
for (a=0;isdigit(c);a=a*10+c-'0',c=nc());
a*=f;return;
}
inline void turn(int &k,int x){
int p=son[k][x];
son[k][x]=son[p][x^1];
son[p][x^1]=k;
t[k].size=t[son[k][0]].size+t[son[k][1]].size+t[k].g;
t[p].size=t[son[p][0]].size+t[son[p][1]].size+t[p].g;
k=p;return;
}
inline void ist(int &k,int x){
if (!k){
k=++size,t[k].w=x,t[k].g=t[k].size=1,t[k].rnd=rand();
return;
}
++t[k].size;
if (t[k].w==x) ++t[k].g;
else if (t[k].w<x){
ist(son[k][1],x);
if (t[son[k][1]].rnd<t[k].rnd) turn(k,1);
}
else{
ist(son[k][0],x);
if (t[son[k][0]].rnd<t[k].rnd) turn(k,0);
}
return;
}
inline void del(int &k,int x){
if (!k) return;
if (t[k].w==x){
if (t[k].g>1){
--t[k].g,--t[k].size;
return;
}
if (son[k][0]*son[k][1]==0) k=son[k][0]+son[k][1];
else if (t[son[k][0]].rnd<t[son[k][1]].rnd) turn(k,0),del(k,x);
else turn(k,1),del(k,x);
}
else{
--t[k].size;
if (t[k].w<x) del(son[k][1],x);
else del(son[k][0],x);
}
return;
}
inline int query(int k,int x){
if (!k||x>t[k].size||x<=0) return 0;
if (t[son[k][0]].size+t[k].g<x) return query(son[k][1],x-t[son[k][0]].size-t[k].g);
else if (t[son[k][0]].size+1>x) return query(son[k][0],x);
else return t[k].w;
}
int main(void){
read(n),read(m);
for (int i=1; i<=n; ++i) read(w[i]);
for (int i=1; i<=m; ++i) read(a[i].x),read(a[i].y),read(a[i].w),a[i].wz=i;
sort(a+1,a+1+m),l=1,r=0;
for (int i=1; i<=m; ++i){
while (r<a[i].y) ist(rt,w[++r]);
while (l<a[i].x) del(rt,w[l++]);
ans[a[i].wz]=query(rt,a[i].w);
}
for (int i=1; i<=m; ++i) printf("%d\n",ans[i]);
return 0;
}