题目链接
这题很多做法都可以过,这里用的是离线 + 平衡树Treap
题目中:给出的区间不互相包含,是离线操作的一个重要条件
我们将给出的区间按左端点从小到大排序,当左端点相同时,按右端点从小到大排序,满足区间访问的元素位置递增(如果有区间互相包含就无法实现)
对于每一个区间 [ l i , r i ] [l_i,r_i] [li,ri],我们将当前平衡树维护的区间的左右端点进行调整,同时进行插入与删除操作
整体来说并不难
#include
#include
#include
#include
#include
using namespace std;
const int Maxn=300000+10,inf=0x3f3f3f3f;
struct node{
int ls,rs,pri,size,val;
#define ls(x) _node[x].ls
#define rs(x) _node[x].rs
#define p(x) _node[x].pri
#define s(x) _node[x].size
#define v(x) _node[x].val
}_node[Maxn];
struct seq{
int l,r,k,pos;
}g[Maxn];
int n,m,root,nodecnt;
int a[Maxn],ans[Maxn];
inline bool cmp(seq x,seq y)
{
if(x.l==y.l)return x.r<y.r;
return x.l<y.l;
}
inline int read()
{
int s=0,w=1;
char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0' && ch<='9')s=(s<<3)+(s<<1)+(ch^48),ch=getchar();
return s*w;
}
inline void push_up(int &x)
{
s(x)=s(ls(x))+s(rs(x))+1;
}
void zag(int &x)
{
int y=rs(x);
rs(x)=ls(y);
ls(y)=x;
s(y)=s(x);
push_up(x);
x=y;
}
void zig(int &x)
{
int y=ls(x);
ls(x)=rs(y);
rs(y)=x;
s(y)=s(x);
push_up(x);
x=y;
}
void ins(int &x,const int k)
{
if(!x)
{
x=++nodecnt,s(x)=1,v(x)=k;
p(x)=((rand()<<16)+rand())%Maxn;
ls(x)=rs(x)=0;
return;
}
++s(x);
if(v(x)>k)
{
ins(ls(x),k);
if(p(ls(x))<p(x))zig(x);
}
else
{
ins(rs(x),k);
if(p(rs(x))<p(x))zag(x);
}
}
void del(int &x,const int k)
{
if(!x)return;
if(v(x)==k)
{
if(!ls(x) || !rs(x)){x=ls(x)|rs(x);return;}
if(p(ls(x))<p(rs(x)))zig(x),del(x,k);
else zag(x),del(x,k);
return;
}
--s(x);
if(v(x)>k)del(ls(x),k);
else del(rs(x),k);
}
int find(int k)
{
int x=root;
while(x)
{
if(k==s(ls(x))+1)return v(x);
if(k<=s(ls(x)))x=ls(x);
else k-=s(ls(x))+1,x=rs(x);
}
return 0;
}
int main()
{
// freopen("in.txt","r",stdin);
srand(time(NULL));
n=read(),m=read();
for(int i=1;i<=n;++i)
a[i]=read();
for(int i=1;i<=m;++i)
{
g[i].l=read(),g[i].r=read();
g[i].k=read(),g[i].pos=i;
}
sort(g+1,g+1+m,cmp);
int l=g[1].l,r=g[1].l;
--r;
for(int i=1;i<=m;++i)
{
int x=g[i].l,y=g[i].r,k=g[i].k;
while(l<x)del(root,a[l]),++l;
while(r<y)++r,ins(root,a[r]);
ans[g[i].pos]=find(k);
}
for(int i=1;i<=m;++i)
printf("%d\n",ans[i]);
return 0;
}