题目:http://oi.tju.edu.cn/problem/view/1113.html
经典的东西。。求排名。
平衡树。。参照某大牛的模版打了一遍。用的treap实现的。。自己用了离散化+线段树实现了一遍。戳爆了。打了接近一个小时才搞定。
平衡树,treap版
#include <cstdio>
#include <cstring>
#include <cstdlib>
#define inf 1000000000
struct node{
int aux,key,cnt,size;
node *left,*right;
};
typedef node *Tnode;
Tnode root,nilpoint;
inline void renew(Tnode &root){
root->size=root->cnt+root->left->size+root->right->size;
}
inline void LeftRotate(Tnode &root){
Tnode t=root->left;
root->left=t->right;
t->right=root;
renew(root);
renew(t);
root=t;
}
inline void RightRotate(Tnode &root){
Tnode t=root->right;
root->right=t->left;
t->left=root;
renew(root);
renew(t);
root=t;
}
inline void Insert(Tnode &root,int key){
if (root==nilpoint)
{
root=new node;
root->left=root->right=nilpoint;
root->key=key;
root->cnt=root->size=1;
root->aux=((rand()<<15)+rand())%inf;
return;
}
if (root->key==key) ++root->cnt;
else if (key<root->key)
{
Insert(root->left,key);
if (root->left->aux<root->aux) LeftRotate(root);
}else if (key>root->key)
{
Insert(root->right,key);
if (root->right->aux<root->aux) RightRotate(root);
}
renew(root);
}
inline void Delete(Tnode &root,int key)
{
if (key==root->key)
{
if (root->left==nilpoint && root->right==nilpoint)
{
if (root->cnt>1) --root->cnt,--root->size;
else root=nilpoint;
return;
}
if (root->left->aux<root->right->aux)
{
LeftRotate(root);
Delete(root->right,key);
}else
{
RightRotate(root);
Delete(root->left,key);
}
renew(root);
return;
}
if (key<root->key) Delete(root->left,key);
else Delete(root->right,key);
renew(root);
}
inline int Query(Tnode &root,int rank)
{
if (rank>root->size) return -1;
if (rank<=root->left->size) return Query(root->left,rank);
if (rank<=root->cnt+root->left->size) return root->key;
return Query(root->right,rank-root->left->size-root->cnt);
}
int main()
{
freopen("arr.in","r",stdin);
freopen("arr.out","w",stdout);
nilpoint=new node;
nilpoint->left=nilpoint->right=nilpoint;
nilpoint->cnt=nilpoint->size=0;
nilpoint->aux=inf;
root=nilpoint;
int n,m;
scanf("%d%d",&n,&m);
for (int i=0;i<m;++i)
{
char op[10];
int x,y;
scanf("%s%d",op,&x);
if (op[0]=='i') Insert(root,x);
else
{
y=Query(root,x);
printf("%d\n",y);
Delete(root,y);
}
}
return 0;
}
离散化+线段树
#include <cmath>
#include <ctime>
#include <iostream>
#include <string>
#include <vector>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
#include <stack>
#include <deque>
using namespace std;
typedef long long LL;
#define eps 10e-9
#define inf 0x3f3f3f3f
const int maxn = 100000+100;
char op[maxn][10];
int a[maxn],c[maxn];
struct node{
int in,v,nv;
bool operator < (const node &c) const {
return v<c.v;
}
}b[maxn];
int sum[maxn<<2],flag[maxn<<2],val[maxn<<2];
void build(int id,int l,int r){
if(l==r){
flag[id]=0; sum[id]=0; return ;
}
int m=(l+r)>>1;
build(id<<1,l,m); build(id<<1|1,m+1,r);
}
void insert(int id,int goal,int l,int r,int op,int v){
if(l==goal&&r==goal){
flag[id]+=op; sum[id]+=op; val[id]=v;
return ;
}
int m=(l+r)>>1;
if(m>=goal){
insert(id<<1,goal,l,m,op,v);
}
else insert(id<<1|1,goal,m+1,r,op,v);
sum[id]=sum[id<<1]+sum[id<<1|1];
}
int inde;
int find(int id,int goal,int l,int r){
int m=(l+r)>>1;
if(l==r){
inde=l;
return val[id];
}
if(sum[id<<1]>=goal){
find(id<<1,goal,l,m);
}
else {
find(id<<1|1,goal-sum[id<<1],m+1,r);
}
}
int main(){
freopen("arr.in","r",stdin);
freopen("arr.out","w",stdout);
int n,m;
scanf("%d %d",&n,&m);
int len=0,l=0;
for(int i=0;i<m;i++){
scanf("%s %d",op[i],&a[i]);
if(op[i][0]=='i'){
b[len].v=a[i]; b[len].in=l++; len++;
}
}
sort(b,b+len);
for(int i=0;i<len;i++) c[ b[i].in ]=i+1;
build(1,1,m);
int cur=0;
for(int i=0;i<m;i++){
if(op[i][0]=='i'){
insert(1,c[cur++],1,m,1,a[i]);
}
else {
printf("%d\n",find(1,a[i],1,m));
insert(1,inde,1,m,-1,0);
}
}
return 0;
}