漂亮小姐姐点击就送:https://www.luogu.org/problemnew/show/P1533
题目背景
小卡由于公务需要出差,将新家中的狗狗们托付给朋友嘉嘉,但是嘉嘉是一个很懒的人,他才没那么多时间帮小卡喂狗狗。
题目描述
小卡家有N只狗,由于品种、年龄不同,每一只狗都有一个不同的漂亮值。漂亮值与漂亮的程度成反比(漂亮值越低越漂亮),吃饭时,狗狗们会按顺序站成一排等着主人给食物。
可是嘉嘉真的很懒,他才不肯喂这么多狗呢,这多浪费时间啊,于是他每次就只给第i只到第j只狗中第k漂亮的狗狗喂食(好狠心的人啊)。而且为了保证某一只狗狗不会被喂太多次,他喂的每个区间(i,j)不互相包含。
输入输出格式
输入格式:
第一行输入两个数n,m,你可以假设n<300001 并且 m<50001;m表示他喂了m次。
第二行n个整数,表示第i只狗的漂亮值为ai。
接下来m行,每行3个整数i,j,k表示这次喂食喂第i到第j只狗中第k漂亮的狗的漂亮值。
输出格式:
M行,每行一个整数,表示每一次喂的那只狗漂亮值为多少。
输入输出样例
输入样例#1: 复制
7 2 1 5 2 6 3 7 4 1 5 3 2 7 1
输出样例#1: 复制
旋转 Treap
Splay
3 2
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=3e5+5; const int INF=599518803; int n,m; int a[N]; struct Query { int l,r,k,tim,ans; }query[N]; struct Node { Node *son[2]; int key; int key_cnt; int size; int heap_key; }node[N],A; typedef Node* Tree; Tree Root,now_node,null; bool cmp1(const Query &a,const Query &b) { return a.l<b.l; } bool cmp2(const Query &a,const Query &b) { return a.tim<b.tim; } void init() { srand(INF); node->son[0]=node->son[1]=node; Root=now_node=null=node; } inline Tree new_node(int key) { ++now_node; now_node->key=key; now_node->key_cnt=1; now_node->heap_key=rand(); now_node->size=1; now_node->son[0]=now_node->son[1]=null; return now_node; } inline void rotate(Tree &root,bool flag) { Tree tmp=root->son[!flag]; root->son[!flag]=tmp->son[flag]; tmp->son[flag]=root; root->size=root->son[0]->size+root->son[1]->size+root->key_cnt; tmp->size=tmp->son[0]->size+tmp->son[1]->size+tmp->key_cnt; root=tmp; } void insert(Tree &root,int key) { if(root==null) root=new_node(key); else if(key==root->key) ++root->size,++root->key_cnt; else { bool flag=key>root->key; insert(root->son[flag],key); ++root->size; if(root->heap_key<root->son[flag]->heap_key) rotate(root,!flag); } } void erase(Tree &root,int key) { if(root==null) return; if(root->key!=key) { bool flag=key>root->key; erase(root->son[flag],key); --root->size; } else { if(root->key_cnt>1) --root->key_cnt,--root->size; if(root->son[0]==null) root=root->son[1]; else if(root->son[1]==null) root=root->son[0]; else { bool flag=root->son[0]->heap_key>root->son[1]->heap_key; rotate(root,flag); erase(root->son[flag],key); --root->size; } } } inline int kth(Tree root,int rank) { while(root!=null) { if(rank<=root->son[0]->size) root=root->son[0]; else if(rank>root->son[0]->size+root->key_cnt) rank-=root->son[0]->size+root->key_cnt,root=root->son[1]; else return root->key; } } int main() { //freopen("testdata.in","r",stdin); //freopen("233.out","w",stdout); init(); scanf("%d%d",&n,&m); for(int i=1;i<=n;++i) scanf("%d",a+i); for(int i=1;i<=m;++i) { scanf("%d%d%d",&query[i].l,&query[i].r,&query[i].k); // query[i].l=read(), // query[i].r=read(), // query[i].k=read(), query[i].tim=i; } sort(query+1,query+m+1,cmp1); for(int i=1;i<=m;++i) { if(i==1) for(int j=query[i].l;j<=query[i].r;++j) insert(Root,a[j]); else { if(query[i-1].r<query[i].l) { for(int j=query[i-1].l;j<=query[i-1].r;++j) erase(Root,a[j]); } else { for(int j=query[i-1].l;j<query[i].l;++j) erase(Root,a[j]); } for(int j=query[i-1].r+1;j<=query[i].r;++j) insert(Root,a[j]); } query[i].ans=kth(Root,query[i].k); } sort(query+1,query+m+1,cmp2); for(int i=1;i<=m;++i) printf("%d ",query[i].ans); return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<cstdio> #include<algorithm> using namespace std; const int N=300005; const int M=5e4+5; int n,m; int a[N]; struct ASK { int l,r,k; int tim,ans; }ask[M]; struct NODE { NODE *fa; NODE *son[2]; int key,key_cnt; int size; }node[N]; typedef NODE* Tree; Tree Root,now_node,null; inline int read() { char c=getchar();int num=0,f=1; for(;!isdigit(c);c=getchar()) f=c=='-'?-1:f; for(;isdigit(c);c=getchar()) num=num*10+c-'0'; return num*f; } bool cmp1(const ASK &a,const ASK &b) { return a.l<b.l; } bool cmp2(const ASK &a,const ASK &b) { return a.tim<b.tim; } inline void init() { node->fa=node->son[0]=node->son[1]=node; Root=now_node=null=node; } inline Tree new_node(int key,Tree fa) { ++now_node; now_node->key=key; now_node->fa=fa; now_node->son[0]=now_node->son[1]=null; return now_node; } inline bool getgx(Tree root) { return root->fa->son[1]==root; } inline void connect(Tree root,Tree fa,bool flag) { if(fa==null) Root=root; else fa->son[flag]=root; if(root!=null) root->fa=fa; } inline void update(Tree root) { root->size=root->son[0]->size+root->son[1]->size+root->key_cnt; } inline void rotate(Tree root) { Tree fa=root->fa; Tree gfa=fa->fa; bool a=getgx(root),b=!a; connect(root->son[b],fa,a); connect(root,gfa,getgx(fa)); connect(fa,root,b); update(fa); update(root); } inline void splay(Tree root,Tree goal) { while(root->fa!=goal) { Tree fa=root->fa; if(fa->fa==goal) rotate(root); else { if(getgx(root)==getgx(fa)) rotate(fa),rotate(root); else rotate(root),rotate(root); } } } inline void insert(int key) { if(Root==null) Root=new_node(key,null); for(Tree root=Root;root!=null;root=root->son[key>root->key]) { if(key==root->key) { ++root->key_cnt; ++root->size; splay(root,null); return; } else if(root->son[key>root->key]==null) root->son[key>root->key]=new_node(key,root); ++root->size; } } inline void erase(int key) { if(Root==null) return; Tree root=Root; for(;root!=null&&root->key!=key;root=root->son[key>root->key]); if(root==null) return; splay(root,null); if(root->son[0]==null) { Root=root->son[1]; if(Root!=null) Root->fa=null; } else if(root->son[1]==null) { Root=root->son[0]; if(Root!=null) Root->fa=null; } else { Tree tmp=root->son[0]; for(;tmp->son[1]!=null;tmp=tmp->son[1]); splay(tmp,root); Root=tmp; Root->fa=null; Root->son[1]=root->son[1]; if(Root->son[1]!=null) Root->son[1]->fa=Root; update(Root); } } inline int query(int rank) { for(Tree root=Root;root!=null;) { if(rank<=root->son[0]->size) root=root->son[0]; else if(rank>root->son[0]->size+root->key_cnt) rank-=root->son[0]->size+root->key_cnt,root=root->son[1]; else return root->key; } } int main() { // freopen("testdata.in","r",stdin); init(); n=read(),m=read(); for(int i=1;i<=n;++i) a[i]=read(); for(int i=1;i<=m;++i) { ask[i].l=read(),ask[i].r=read(),ask[i].k=read(); ask[i].tim=i; } sort(ask+1,ask+m+1,cmp1); int l=ask[1].l,r=l; for(int i=1;i<=m;++i) { for(;l<ask[i].l;++l) erase(a[l]); for(;r<=ask[i].r;++r) insert(a[r]); ask[i].ans=query(ask[i].k); } sort(ask+1,ask+m+1,cmp2); for(int i=1;i<=m;++i) printf("%d ",ask[i].ans); return 0; }