利用区间的有序性才可以用treap 其实这题 线段树和树状数组时更好的选择 稍后补上
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<iostream>
using namespace std;
const int inf=~0U>>1;
class treap
{
struct node
{
int val,key,size;
node *c[2];
node(int v,node *x){val=v,c[0]=c[1]=x,size=1;key=rand()-1;}
void rz(){size=c[0]->size+c[1]->size+1;}
}*root,*null;
void ro(node *&x,bool d)
{
node *t=x->c[d];
x->c[d]=t->c[!d];
t->c[!d]=x;
x->rz();t->rz();x=t;
}
void insert(node *&x,int v)
{
if(x==null) {x=new node(v,null);return;}
// if(x->val==v) return ;
bool d=(v>=x->val);
insert(x->c[d],v);
if(x->c[d]->key<x->key)
ro(x,d); else x->rz();
}
void dele(node*&x,int v)
{
if(x==null) return ;
if(x->val==v)
{
bool d=x->c[0]->key>x->c[1]->key;
if(x->c[d]==null)
{
x=null;
return ;
}
ro(x,d);
dele(x->c[!d],v);
}
else
{
bool d=v>x->val;
dele(x->c[d],v);
}
x->rz();
}
int select(node *x,int k)
{
if(x->c[0]->size==k) return x->val;
else if(x->c[0]->size>k) return select(x->c[0],k);
else return select(x->c[1],k-x->c[0]->size-1);
}
int ran(node *x,int v)
{
if(x==null) return 0;
if(x->val==v) return x->c[0]->size;
if(x->val>v) return ran(x->c[0],v);
else return ran(x->c[1],v)+1+x->c[0]->size;
}
void pr(node *x) {if(x!=null) {pr(x->c[0]);cout<<x->val<<" ";pr(x->c[1]);}}
public:
treap(){null=new node(0,0);null->size=0;null->key=inf;root=null;}
void ins(int v){insert(root,v);}
void del(int v){dele(root,v);}
int rank(int v){return ran(root,v);}
int find_k(int k){if(root->size<k) return -inf;return select(root,k-1);}
void pr(){pr(root);puts("");}
};
int n,m;
int val[111111];
struct query
{
int l,r,id,k;
bool operator <(query q)
{
return l<q.l||(l==q.l&&r<q.r);
}
}a[55555];
int ans[55555];
template <class T>
void quicksort(T *p,int s,int e)
{
if(s<e)
{
int i=s,j=e;T tmp=p[e];
while(i<j)
{
while(i<j&&p[i]<tmp) ++i;
if(i<j) p[j--]=p[i];
while(i<j&&tmp<p[j]) --j;
if(i<j) p[i++]=p[j];
}
p[i]=tmp;
quicksort(p,s,i-1);
quicksort(p,i+1,e);
}
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
treap T;
for(int i=1;i<=n;++i)
{
scanf("%d",val+i);
}
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&a[i].l,&a[i].r,&a[i].k);
a[i].id=i;
}
quicksort(a,1,m);
for(int i=1;i<=m;++i)
{
//cout<<a[i].l<<" "<<a[i].r<<" "<<a[i].k<<" "<<a[i].id;
int d=(a[i-1].r<a[i].l-1)?a[i-1].r:a[i].l-1;
int in=(a[i-1].r+1>a[i].l)?a[i-1].r+1:a[i].l;
// cout<<" "<<d<<" "<<in<<endl;
if(i>1) for(int j=a[i-1].l;j<=d;++j)
T.del(val[j]);
for(int j=in;j<=a[i].r;++j)
T.ins(val[j]);
ans[a[i].id]=T.find_k(a[i].k);
// T.pr();
}
for(int i=1;i<=m;++i)
printf("%d\n",ans[i]);
}
return 0;
}
我次奥 换成系统的sort 直接变成 3000ms
线段树版本
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define N 111111
using namespace std;
int sum[N<<2];
void pup(int rt)
{
sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void update(int p,int add,int l,int r,int rt)
{
if(l==r)
{
sum[rt]+=add;
return;
}
int mid=(l+r)>>1;
if(p<=mid) update(p,add,lson);
else update(p,add,rson);
pup(rt);
}
int que(int k,int l,int r,int rt)
{
if(l==r) return l;
int mid=(l+r)>>1;
if(k<=sum[rt<<1])
return que(k,lson);
else
return que(k-sum[rt<<1],rson);
}
struct ps
{
int id,val;
}a[111111];
int va[111111];
int cmp(ps p,ps q){return p.val<q.val;}
int n,m;
struct pp
{
int l,r,id,k;
}q[55555];
int cmp2(pp p,pp q){return p.l<q.l;}
int ans[55555];
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i].val);
a[i].id=i;
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;++i)
va[a[i].id]=i;
memset(sum,0,sizeof(sum));
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);
q[i].id=i;
}
sort(q+1,q+1+m,cmp2);
for(int i=q[1].l;i<=q[1].r;++i)
update(va[i],1,1,n,1);
ans[q[1].id]=que(q[1].k,1,n,1);
for(int i=2;i<=m;++i)
{
int d,in;
d=(q[i-1].r<q[i].l-1)?q[i-1].r:q[i].l-1;
in=(q[i-1].r+1<q[i].l)?q[i].l:q[i-1].r+1;
for(int j=q[i-1].l;j<=d;++j)
update(va[j],-1,1,n,1);
for(int j=in;j<=q[i].r;++j)
update(va[j],1,1,n,1);
ans[q[i].id]=que(q[i].k,1,n,1);
}
for(int i=1;i<=m;++i)
printf("%d\n",a[ans[i]].val);
}
return 0;
}
下面是树状数组
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define N 111111
using namespace std;
int sum[N];
struct ps
{
int id,val;
}a[111111];
int va[111111];
int cmp(ps p,ps q){return p.val<q.val;}
int n,m;
struct pp
{
int l,r,id,k;
}q[55555];
int cmp2(pp p,pp q){return p.l<q.l;}
int ans[55555];
int lowbit(int x){return x&(x^(x-1));}
void update(int p,int add)
{
for(;p<=n;p+=lowbit(p))
sum[p]+=add;
}
int qu(int p)
{
int res;
for(res=0;p;p-=lowbit(p))
res+=sum[p];
return res;
}
int que(int k)
{
int l=1,r=n,mid;
for(;l<=r;)
{
mid=(l+r)>>1;
int res=qu(mid);
if(res>=k) r=mid-1;
else l=mid+1;
}
return l;
}
int main()
{
while(scanf("%d%d",&n,&m)==2)
{
for(int i=1;i<=n;++i)
{
scanf("%d",&a[i].val);
a[i].id=i;
}
sort(a+1,a+1+n,cmp);
for(int i=1;i<=n;++i)
va[a[i].id]=i;
memset(sum,0,sizeof(sum));
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);
q[i].id=i;
}
sort(q+1,q+1+m,cmp2);
for(int i=q[1].l;i<=q[1].r;++i)
update(va[i],1);
ans[q[1].id]=que(q[1].k);
for(int i=2;i<=m;++i)
{
int d,in;
d=(q[i-1].r<q[i].l-1)?q[i-1].r:q[i].l-1;
in=(q[i-1].r+1<q[i].l)?q[i].l:q[i-1].r+1;
for(int j=q[i-1].l;j<=d;++j)
update(va[j],-1);
for(int j=in;j<=q[i].r;++j)
update(va[j],1);
ans[q[i].id]=que(q[i].k);
}
for(int i=1;i<=m;++i)
printf("%d\n",a[ans[i]].val);
}
return 0;
}