[BZOJ4923][Lydsy六月份月赛 .G][平衡树]K小值查询

来源:互联网 发布:丽水学院网络教学平台 编辑:程序博客网 时间:2024/06/06 07:34

直接上题解
这里写图片描述

学了发非旋转Treap,感觉常数有点大

#include <cstdio>#include <iostream>#include <algorithm>using namespace std;const int N=100010;int n,m;int a[N];struct node{  node *l,*r;  int val,fix,size,minus;  node(){ }  node(int x):val(x),fix(rand()),size(1),l(NULL),r(NULL),minus(0){}  void Push(){    if(!minus) return ;    if(l) l->val-=minus,l->minus+=minus;    if(r) r->val-=minus,r->minus+=minus;    minus=0;  }  void Up(){    size=(l?l->size:0)+(r?r->size:0)+1;  }  int mark(int x){    val-=x; minus+=x;  }}poor[N],*rt;inline char nc(){  static char buf[100000],*p1=buf,*p2=buf;  return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;}inline void rea(int &x){  char c=nc(); x=0;  for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());}inline int Size(node *x){    return x?x->size:0;}typedef pair<node*,node*> Droot;inline node *newnode(int x,int p){  poor[p].val=x; poor[p].fix=rand(); poor[p].size=1; return poor+p;}inline node *Merge(node *x,node *y){  if(!x||!y) return !x?y:x;  x->Push(); y->Push();  if(x->fix<y->fix){    x->r=Merge(x->r,y);    x->Up(); return x;  }  else{    y->l=Merge(x,y->l);    y->Up(); return y;  }}inline node *Query(int k){  node *x=rt;  while(x){    x->Push();    if(k==Size(x->l)+1) return x;    if(k>Size(x->l)) k-=Size(x->l)+1,x=x->r;    else x=x->l;    }    return 0;}inline int Rank(int k){    node *x=rt; int ret=0;    while(x){        x->Push();        if(x->val<k) ret+=Size(x->l)+1,x=x->r;        else x=x->l;    }    return ret+1;}Droot Split(node *x,int k){    if(!x) return Droot(NULL,NULL);    x->Push();    if(k<=Size(x->l)){        Droot ret=Split(x->l,k);        x->l=ret.second; x->Up();        ret.second=x; return ret;    }    else{        Droot ret=Split(x->r,k-Size(x->l)-1);        x->r=ret.first; x->Up();        ret.first=x; return ret;    }}bool Modify(int k){    int cur=Rank(k+1);    node *p=Query(cur);    if(!p||p->val>2*k) return false;    Droot x=Split(rt,cur-1);    Droot y=Split(x.second,1);    y.first->val-=k;    rt=Merge(x.first,y.second);    cur=Rank(y.first->val);    x=Split(rt,cur-1);    rt=Merge(x.first,Merge(y.first,x.second));    return true;}int opt,k;int main(){  rea(n); rea(m);  for(int i=1;i<=n;i++) rea(a[i]);  sort(a+1,a+1+n);  for(int i=1;i<=n;i++)    poor[i]=node(a[i]),rt=Merge(rt,poor+i);  while(m--){    rea(opt); rea(k);    if(opt==1) printf("%d\n",Query(k)->val);    else{      while(Modify(k));      int cur;      if((cur=Rank(k+1))<=n){        Droot x=Split(rt,cur-1);        x.second->mark(k);        rt=Merge(x.first,x.second);      }    }  }  return 0;}