3196: Tyvj 1730 二逼平衡树
2015-08-22 21:01
417 查看
/************************************************************** Problem: 3196 User: moonbeam Language: C++ Result: Accepted Time:5236 ms Memory:27600 kb ****************************************************************/ #include<cstdio> #include<cstdlib> #include<algorithm> using namespace std; #define nn 50010 #define inf 0x7fffffff class multi_treap//multi_treap和treap类似,也是一种排序二叉树,但支持重复元素,其他功能上和treap一样 { private: struct node//multi_treap的节点定义 { node* ch[2]; int v, r, s, num; int cmp(int x) { if (x == v) return -1; return(x < v ? 0 : 1); } }; node *root;//multi_treap的根 void updata(node* o) { if (!o) return; o->s = o->num; if (o->ch[0]) o->s += o->ch[0]->s; if (o->ch[1]) o->s += o->ch[1]->s; } void rateto(node* &o, int d) { node* k; k = o->ch[d ^ 1]; o->ch[d ^ 1] = k->ch[d]; k->ch[d] = o; updata(o); updata(k); o = k; } void add(node* &o, int x) { if (!o) { o = new node(); o->ch[0] = o->ch[1] = 0; o->v = x; o->r = rand()*rand(); o->s = 1; o->num = 1; return; } int d = o->cmp(x); if (d == -1) { o->num++;//multi的开关,注释掉可以关闭multi功能 o->s++; } else { add(o->ch[d], x); updata(o); if (o->r < o->ch[d]->r) rateto(o, d ^ 1); } } void remove(node* &o, int x) { int d = o->cmp(x); if (d == -1) { if (o->num>1) { o->num--; o->s--; } else { if (!(o->ch[0])) { node *p = o; o = o->ch[1]; free(p); p = 0; } else if (!(o->ch[1])) { node *p = o; o = o->ch[0]; free(p); p = 0; } else { int d2 = o->ch[0]->r > o->ch[1]->r ? 1 : 0; rateto(o, d2); remove(o->ch[d2], x); } } } else remove(o->ch[d], x); updata(o); } int left(node* o) { if (o->ch[0]) return o->ch[0]->s; else return 0; } int Kth(int k) { node *p = root; while (1) { int su = (p->ch[0] ? p->ch[0]->s : 0); if (su + 1 <= k&&k <= su + p->num) return p->v; else if (k <= su) p = p->ch[0]; else { k -= su + p->num; p = p->ch[1]; } } } int Rank(int x) { int ans = 0; node *p = root; while (p) { if (p->v == x) { ans += 1 + (p->ch[0] ? p->ch[0]->s : 0); return ans; } else if (x < p->v) p = p->ch[0]; else { ans += p->num + (p->ch[0] ? p->ch[0]->s : 0); p = p->ch[1]; } } return ans+1; } int RankPlus(int x) { int ans = 0; node *p = root; while (p) { if (p->v == x) { ans += p->num + (p->ch[0] ? p->ch[0]->s : 0); return ans; } else if (x < p->v) p = p->ch[0]; else { ans += p->num + (p->ch[0] ? p->ch[0]->s : 0); p = p->ch[1]; } } return ans; } int Suc(int x) { node* p = root; int ans = 0; bool find = 0; while (p) { if (p->v > x) { ans = p->v; find = 1; } p = p->ch[p->v <= x]; } if (find) return ans; else return -1; } int Pre(int x) { node *p = root; int ans = 0; bool find = 0; while (p) { if (p->v < x) { ans = p->v; find = 1; } p = p->ch[p->v < x]; } if (find) return ans; else return -1; } bool Find(node* o, int x) { while (o) { int d = o->cmp(x); if (d == -1) return 1; else o = o->ch[d]; } return 0; } void mymemory(node* &o) { if (!o) return; if (o->ch[0]) mymemory(o->ch[0]); if (o->ch[1]) mymemory(o->ch[1]); free(o); o = 0; } //以上是multi_treap的实现部分 public: int size() //返回multi_treap中元素的个数 { if (root) return root->s; else return 0; } void insert(int x)//在multi_treap中插入一个x { add(root, x); } void erase(int x)//删除multi_treap中的元素x,如果multi_treap中x的有多个,则只删除一个 { remove(root, x); } int kth(int x) //返回multi_treap中排名为x的元素的值,如果x非法,则返回-1 { if (x <= 0 || x > size()) return -1; else return Kth(x); } int rank(int x) //返回x在multi_treap中的排名,如果x没有在multi_treap中,则返回-1 { return Rank(x); } int suc(int x) //返回multi_treap中大于x的第一个元素的值(后驱),如果x大于等于multi_treap中的最大值,则返回-1 { return Suc(x); } int pre(int x) //返回multi_treap中小于x的第一个元素的值(前驱),如果x小于等于multi_treap中的最小值,则返回-1 { return Pre(x); } bool find(int x) //返回x是否在该multi_treap { return Find(root, x); } void clear() //清空multi_treap { mymemory(root); } multi_treap() //multi_treap初始化 { root = 0; } int rankplus(int x) { return RankPlus(x); } }treap[nn<<1]; int val[nn],use[nn]; int cnt; void build(int l,int r) { int id=l+r|l!=r; for(int i=l;i<=r;i++) treap[id].insert(val[i]); if(l==r) return; int mid=(l+r)>>1; build(l,mid); build(mid+1,r); } void choose(int l,int r,int ll,int rr) { int id=l+r|l!=r; if(ll<=l && r<=rr){ use[cnt++]=id; return; } int mid=(l+r)>>1; if(ll<=mid) choose(l,mid,ll,rr); if(rr>mid) choose(mid+1,r,ll,rr); } void change(int l,int r,int rt,int v) { int id=l+r|l!=r; treap[id].erase(val[rt]); treap[id].insert(v); if(l==r) return; int mid=(l+r)>>1; if(rt<=mid) change(l,mid,rt,v); else change(mid+1,r,rt,v); } int main() { int n,m; for(int i=0;i<(nn<<1);i++) treap[i].clear(); while(~scanf("%d%d",&n,&m)) { for(int i=1;i<=n;i++) scanf("%d",&val[i]); build(1,n); while(m--) { int opt; scanf("%d",&opt); if(opt==3) { int pos,k; scanf("%d%d",&pos,&k); change(1,n,pos,k); val[pos]=k; continue; } int l,r,k; scanf("%d%d%d",&l,&r,&k); cnt=0; choose(1,n,l,r); //printf("cnt==%d\n",cnt); // for(int i=0;i<cnt;i++) // printf("%d ",use[i]); // printf("\n"); if(opt==1) { int ans=0; for(int i=0;i<cnt;i++) ans+=treap[use[i]].rank(k)-1; printf("%d\n",ans+1); } else if(opt==2) { int ll=-1,rr=1e8+10; while(ll<rr) { int mid=(ll+rr)>>1; int ans=0; for(int i=0;i<cnt;i++) ans+=treap[use[i]].rank(mid)-1; if(ans+1<=k) ll=mid+1; else rr=mid; } printf("%d\n",rr-1); } else if(opt==4) { int ans=-inf; for(int i=0;i<cnt;i++) { int tmp=treap[use[i]].pre(k); if(tmp!=-1) ans=max(ans,tmp); } printf("%d\n",ans); } else if(opt==5) { int ans=inf; for(int i=0;i<cnt;i++) { int tmp=treap[use[i]].suc(k); if(tmp!=-1) ans=min(ans,tmp); } printf("%d\n",ans); } } for(int i=0;i<(nn<<1);i++) treap[i].clear(); } return 0; }
相关文章推荐
- HBase 简介以及个人理解(原理,基本概念,基本架构)
- 浪潮Inspur K-UX操作系统的截图
- [洛谷2415]集合求和
- 两个字符串的最大公共子串
- MySQL性能测试(二)——Ubuntu 14.4.02, MySQL 5.6.25, sysbench 4.8
- C语言-10
- Basic Calculator
- SGU 102(Coprimes)
- Linux crontab定时执行任务 命令格式与详细例子
- 大图处理
- Selenium的封装与重用
- js 正则表达式一看就懂
- Mybatis基础操作
- 里氏替换原则
- HDU_1754 I Hate It(线段树)
- Add Digits
- java中string与json互相转化
- 我多希望我学编程时,有人教我这些事!
- 5种类型的程序员
- java file 删除目录下无用的文件