标签:
Description
Input
Output
Sample Input
7 2 1 5 2 6 3 7 4 1 5 3 2 7 1
Sample Output
3 2
题意:查询一段区间的第k大值,而且题目保证查询区间是不存在包含关系。
解析:因为不存在包含关系,所以直接离线排序,向右插入元素,向右删除元素。利用treap树实现名次树的功能。
代码
#include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> using namespace std; const int INF=1e9+7; const int maxn=100005; int A[maxn],cnt; //A数组保存数,cnt是节点标号,我是用数组模拟的 struct treap { treap* son[2]; //左右儿子 int v,s,r; treap(){ v=s=r=0; son[0]=son[1]=NULL; } treap(int nv,int nr); int rk(){ return son[0]->s+1; } //排名,第几个数 int cmp(int k) //比较,如果相等返回-1,小于返回0,大于1 { if(k==v) return -1; return k<v?0:1; } void pushup(){ s=son[0]->s+son[1]->s+1; } //更新大小 }null,tr[maxn]; treap::treap(int nv,int nr) { v=nv; r=nr; s=1; son[0]=son[1]=&null; } treap* NewNode(int x,int r)//建新节点 { tr[cnt]=treap(x,r); return tr+cnt++; } struct splaytree { int Size; treap* root; splaytree(){ Size=0; root=&null; } void Rotate(treap* &t,int d) //翻转操作 { treap* p=t->son[d^1]; t->son[d^1]=p->son[d]; p->son[d]=t; t->pushup(); //要更新 t=p; t->pushup(); } void Insert(treap* &t,int x,int r) //插入 { if(t==&null) //插入 { t=NewNode(x,r); //申请新节点 return; } int d=t->cmp(x); if(d==-1) d=1; //往右边走 Insert(t->son[d],x,r); if(t->son[d]->r > t->r) Rotate(t,d^1); //旋转 t->pushup(); } void Remove(treap* &t,int x) //删除 { int d=t->cmp(x); if(d==-1) { if(t->son[0]==&null) t=t->son[1]; else if(t->son[1]==&null) t=t->son[0]; else { int d2=(t->son[0]->r > t->son[1]->r ? 1: 0); Rotate(t,d2); Remove(t->son[d2],x); } } else Remove(t->son[d],x); if(t!=&null) t->pushup(); } int Query(treap* &t,int kth) //查询 { if(t==&null||kth<=0||kth>t->s) return -1; int a=t->rk(); if(kth==a) return t->v; else if(kth<a) return Query(t->son[0],kth); else return Query(t->son[1],kth-a); } }; int N,M; struct Ques { int x,y,k,id; Ques(int x=0,int y=0,int k=0,int id=0):x(x),y(y),k(k),id(id){} bool operator < (const Ques& t) const { if(x!=t.x) return x<t.x; return y<t.y; } }q[maxn]; int ans[maxn]; int main() { scanf("%d%d",&N,&M); splaytree spt; cnt=0; for(int i=1;i<=N;i++) scanf("%d",&A[i]); int x,y,k; for(int i=0;i<M;i++) //输入 { scanf("%d%d%d",&x,&y,&k); q[i]=Ques(x,y,k,i); } sort(q,q+M); //排序 int f=1,r=1; for(int i=0;i<M;i++) { Ques& t=q[i]; int x=t.x,y=t.y,k=t.k; for(;f<x;f++) if(f<r) spt.Remove(spt.root,A[f]); if(r<f) r=f; for(;r<=y;r++) spt.Insert(spt.root,A[r],rand()); ans[t.id]=spt.Query(spt.root,k); //保存答案 } for(int i=0;i<M;i++) printf("%d\n",ans[i]); return 0; }
标签:
原文地址:http://www.cnblogs.com/wust-ouyangli/p/5733955.html