利用区间的有序性才可以用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; }