离线的题目,莫队是不错的解决方法
先把询问排一下序
剩下就套一个莫队的板子
每来一只狗就把漂亮值插入平衡树
每去掉一只狗就把漂亮值从平衡树中删掉
每次查询查平衡树中第k小
#pragma GCC optimize("O3")
#include <bits/stdc++.h>
#define N 800005
#define M 50005
using namespace std;
inline char nc(){
static char buf[100000],*p1=buf,*p2=buf;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
inline int read()
{
register int x=0,f=1;register char ch=nc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=nc();}
while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=nc();
return x*f;
}
inline void write(register int x)
{
if(!x)putchar('0');if(x<0)x=-x,putchar('-');
static int sta[20];register int tot=0;
while(x)sta[tot++]=x%10,x/=10;
while(tot)putchar(sta[--tot]+48);
}
struct Splay{
int v,fa,ch[2],sum,rec;
}tree[N];
int tot=0;
inline void update(register int x)
{
tree[x].sum=tree[tree[x].ch[0]].sum+tree[tree[x].ch[1]].sum+tree[x].rec;
}
inline bool findd(register int x)
{
return tree[tree[x].fa].ch[0]==x?0:1;
}
inline void connect(register int x,register int fa,register int son)
{
tree[x].fa=fa;
tree[fa].ch[son]=x;
}
inline void rotate(register int x)
{
int Y=tree[x].fa;
int R=tree[Y].fa;
int Yson=findd(x);
int Rson=findd(Y);
int B=tree[x].ch[Yson^1];
connect(B,Y,Yson);
connect(Y,x,Yson^1);
connect(x,R,Rson);
update(Y),update(x);
}
inline void splay(register int x,register int to)
{
to=tree[to].fa;
while(tree[x].fa!=to)
{
int y=tree[x].fa;
if(tree[y].fa==to)
rotate(x);
else if(findd(x)==findd(y))
rotate(y),rotate(x);
else
rotate(x),rotate(x);
}
}
inline int newpoint(register int v,register int fa)
{
tree[++tot].fa=fa;
tree[tot].v=v;
tree[tot].sum=tree[tot].rec=1;
return tot;
}
inline void Insert(register int x)
{
int now=tree[0].ch[1];
if(tree[0].ch[1]==0)
{
newpoint(x,0);
tree[0].ch[1]=tot;
}
else
{
while(19260817)
{
++tree[now].sum;
if(tree[now].v==x)
{
++tree[now].rec;
splay(now,tree[0].ch[1]);
return;
}
int nxt=x<tree[now].v?0:1;
if(!tree[now].ch[nxt])
{
int p=newpoint(x,now);
tree[now].ch[nxt]=p;
splay(p,tree[0].ch[1]);
return;
}
now=tree[now].ch[nxt];
}
}
}
inline int find(register int v)
{
int now=tree[0].ch[1];
while(19260817)
{
if(tree[now].v==v)
{
splay(now,tree[0].ch[1]);
return now;
}
int nxt=v<tree[now].v?0:1;
if(!tree[now].ch[nxt])
return 0;
now=tree[now].ch[nxt];
}
}
inline void delet(register int x)
{
int pos=find(x);
if(!pos)
return;
if(tree[pos].rec>1)
{
--tree[pos].rec;
--tree[pos].sum;
}
else
{
if(!tree[pos].ch[0]&&!tree[pos].ch[1])
tree[0].ch[1]=0;
else if(!tree[pos].ch[0])
{
tree[0].ch[1]=tree[pos].ch[1];
tree[tree[0].ch[1]].fa=0;
}
else
{
int left=tree[pos].ch[0];
while(tree[left].ch[1])
left=tree[left].ch[1];
splay(left,tree[pos].ch[0]);
connect(tree[pos].ch[1],left,1);
connect(left,0,1);
update(left);
}
}
}
inline int arank(register int x)
{
int now=tree[0].ch[1];
while(19260817)
{
int used=tree[now].sum-tree[tree[now].ch[1]].sum;
if(x>tree[tree[now].ch[0]].sum&&x<=used)
{
splay(now,tree[0].ch[1]);
return tree[now].v;
}
if(x<used)
now=tree[now].ch[0];
else
x-=used,now=tree[now].ch[1];
}
}
struct query{
int l,r,id,bl,k;
}q[M];
int a[N],blocksize=0,ans[M];
inline bool cmp(register query a,register query b)
{
return a.bl!=b.bl?a.l<b.l:((a.bl&1)?a.r<b.r:a.r>b.r);
}
int main()
{
int n=read(),m=read();
blocksize=sqrt(m);
for(register int i=1;i<=n;++i)
a[i]=read();
for(register int i=1;i<=m;++i)
{
int l=read(),r=read(),k=read();
q[i]=(query){l,r,i,l/blocksize,k};
}
sort(q+1,q+m+1,cmp);
int l=1,r=0;
for(register int i=1;i<=m;++i)
{
int ll=q[i].l,rr=q[i].r;
while(ll<l)
Insert(a[--l]);
while(rr>r)
Insert(a[++r]);
while(ll>l)
delet(a[l++]);
while(rr<r)
delet(a[r--]);
ans[q[i].id]=arank(q[i].k);
}
for(register int i=1;i<=m;++i)
write(ans[i]),puts("");
return 0;
}