poj 2761 Feed the dogs 平衡树,线段树,树状数组
来源:互联网 发布:物联网如何传输数据 编辑:程序博客网 时间:2024/06/05 06:41
分析:这题就是求区间第k小数,但是这题和poj2104的区别就是,2104的区间是可以完全包含的,就是说某个点进出区间不止一次,所以平衡树和线段树是超时的,只能用划分树或者归并树,这题是可以用平衡树解的。先把区间从左到右排序,然后依次插入平衡树,线段树,然后利用树的性质在log n 内找到第k小。这题也可以用树状数组解,但是需要二分第k小,我一直觉得二分不是最好的做法,考虑能不能在log n内用树状数组找到第k小,一直做不到,所以这题没用树状数组写。
再说一下,平衡树中,treap最好写,sbt据说最快,而且附加域是有用的,是树的节点个数size,而伸展树很灵活可以快速合并分裂翻转,可以实现其他平衡树做不到的。
个人认为,必须要学会伸展树,然后SBT和treap一定要会一种。我学的是SBT。
然后,线段树需要先对数据二分+离散化,因为可能出现很大的值,很浪费内存。
因为要对区间排序,所以要保存区间的顺序下标,最后输出答案有两种方法,一种是获得解后重新按照区间出现顺序排序,第二种是直接ans[interval[i].index]=interval[i].k;
下面是三种不同的解法,线段树,SBT,伸展树。
最后,因为这一题开始只用了线段树写的,后面两种写法是后来学平衡树的时候写的,所以在判断区间重叠的时候不一样。后面多考虑了区间完全重叠的情况,这个数据是没有的,只是为了对拍数据用的。可以删掉。
线段树:
#include<cstdio>#include<cstring>#include<algorithm>using namespace std;#define N 100005#define M 50005int n,m;int pretty[N];int dog[N];struct inter{ int l,r,k; int ans; int index;}interval[M];struct tree{ int l,r,p;}tree[N<<2];int binary(int key){ int l=1,r=n; while(l<=r){ int mid=(l+r)>>1; if(pretty[mid]==key) return mid; else if(key<pretty[mid]) r=mid-1; else l=mid+1; }}void build(int rt,int l,int r){ tree[rt].l=l;tree[rt].r=r; if(l<r){ int mid=(l+r)>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); }}void insert(int rt,int i,int d){ tree[rt].p+=d; if(tree[rt].l!=tree[rt].r){ int mid=(tree[rt].l+tree[rt].r)>>1; if(mid>=i) insert(rt<<1,i,d); else insert(rt<<1|1,i,d); }}inline bool cmp(const inter &a, const inter &b){ return a.l<b.l||(a.l==b.l&&a.r<b.r);}inline bool operator<(const inter &a, const inter &b){ return a.index<b.index;}int query(int rt,int k){ if(tree[rt].l==tree[rt].r) return pretty[tree[rt].l]; if(tree[rt<<1].p>=k) return query(rt<<1,k); else return query(rt<<1|1,k-tree[rt<<1].p);}int main(){ memset(tree,0,sizeof(tree)); scanf("%d%d",&n,&m); for(int i=1; i<=n; i++){ scanf("%d",pretty+i); dog[i]=pretty[i]; } for(int i=1;i<=m;i++){ scanf("%d%d%d",&interval[i].l,&interval[i].r,&interval[i].k); interval[i].index=i; } sort(pretty+1,pretty+n+1); sort(interval+1,interval+m+1,cmp); for(int i=1;i<=n;i++) dog[i]=binary(dog[i]); build(1,1,n); for(int i=interval[1].l;i<=interval[1].r;i++) insert(1,dog[i],1); interval[1].ans=query(1,interval[1].k); for(int i=2;i<=m;i++){ if(interval[i].l<=interval[i-1].r){ for(int j=interval[i-1].l;j<interval[i].l;j++) insert(1,dog[j],-1); for(int j=interval[i-1].r+1;j<=interval[i].r;j++) insert(1,dog[j],1); }else{ for(int j=interval[i-1].l;j<=interval[i-1].r;j++) insert(1,dog[j],-1); for(int j=interval[i].l;j<=interval[i].r;j++) insert(1,dog[j],1); } interval[i].ans=query(1,interval[i].k); } sort(interval+1,interval+m+1); for(int i=1;i<=m;i++) printf("%d\n",interval[i].ans); return 0;}
SBT:
#include<cstdio>#include<algorithm>const int maxn = 100009;const int maxm = 50009;struct cnode{cnode *lchild,*rchild;int s,key;}node[maxn];int sz=1;inline cnode *newnode(cnode*l,cnode*r,int s,int key){node[sz].lchild=l;node[sz].rchild=r;node[sz].s=s;node[sz].key=key;return node+sz++;}struct SBT{cnode *root;cnode *null;SBT(){root=null=node;node[0].s=0;node[0].key=-1;null->lchild=null->rchild=null;}~SBT(){root=null=NULL;}void rotate_r(cnode*&t){cnode *temp=t->lchild;t->lchild=temp->rchild;temp->rchild=t;temp->s=t->s;t->s=t->lchild->s+t->rchild->s+1;t=temp;}void rotate_l(cnode*&t){cnode *temp=t->rchild;t->rchild=temp->lchild;temp->lchild=t;temp->s=t->s;t->s=t->lchild->s+t->rchild->s+1;t=temp;}void maintain(cnode*&t,bool type){if(t==null)return;if(!type){if(t->lchild->lchild->s > t->rchild->s){rotate_r(t);}else if(t->lchild->rchild->s > t->rchild->s){rotate_l(t->lchild);rotate_r(t);}else return;}else{if(t->rchild->rchild->s > t->lchild->s){rotate_l(t);}else if(t->rchild->lchild->s > t->lchild->s){rotate_r(t->rchild);rotate_l(t);}else return;}maintain(t->lchild,false); maintain(t->rchild,true);maintain(t,false);maintain(t,true);}void insert(cnode*&t,int key){if(t==null){t=newnode(null,null,1,key);return;}t->s++;if(key < t->key) insert(t->lchild,key);else insert(t->rchild,key);maintain(t,key>=root->key);}void erase(cnode*&t,int key){if(t==null) return;t->s--;if(t->key==key){if(t->lchild!=null&&t->rchild==null){t=t->lchild;}else if( t->lchild==null && t->rchild==null){t=null;}else{cnode*temp=t->rchild;while(temp->lchild!=null){temp=temp->lchild;}t->key=temp->key;erase(t->rchild,temp->key);}}else if(key<t->key){erase(t->lchild,key);}else{erase(t->rchild,key);}}int kth(int k){//printf("s: %d",root->s);//travel();cnode *t=root;while(1){if(t->lchild->s==k-1)return t->key;else if(t->lchild->s > k-1){t=t->lchild;}else{k-=1+t->lchild->s;t=t->rchild;}}}void erase(int key){erase(root,key);}void insert(int key){insert(root,key);}void travel(){travel(root);}void travel(cnode *t){if(t!=null){travel(t->lchild);printf("%d %d\n",t->s,t->key);travel(t->rchild);}}};SBT tree;struct A{int l,r,k,i;}interval[maxn];int a[maxn];bool cmp2(const A&a,const A&b){return a.l<b.l||a.l==b.l&&a.r<b.r;}bool cmp(const A&a,const A&b){return a.i<b.i;}int main(){int m,n;scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d",a+i);}for(int i=0;i<m;i++){scanf("%d %d %d",&interval[i].l,&interval[i].r,&interval[i].k);interval[i].i=i;}std::sort(interval,interval+m,cmp2);int r=interval[0].r,l=interval[0].l;for(int i=l;i<=r;i++) tree.insert(a[i]);interval[0].k=tree.kth(interval[0].k);for(int i=1;i<m;i++){int R=interval[i].r,L=interval[i].l;if(L>r){while(l<=r){tree.erase(a[l++]);}l=L;r=R;while(L<=R){tree.insert(a[L++]);}}else if(R>r){while(l<L){tree.erase(a[l++]);}while(++r<=R){tree.insert(a[r]);}--r;}else{while(l<L){tree.erase(a[l++]);}while(r>R){tree.erase(a[r--]);}}interval[i].k=tree.kth(interval[i].k);}std::sort(interval,interval+m,cmp);for(int i=0;i<m;i++)printf("%d\n",interval[i].k);return 0;}Splay:
#include<cstdio>#include<algorithm>const int INF = (unsigned(~0))>>1;const int maxm = 50009;const int maxn = 100009;struct splaytree{ int sz; struct node{ int s,v; node *parent; node *child[2]; }; node pool[maxn]; node* null; node* root; node nil; splaytree(){ root=null=&nil; nil.parent=nil.child[0]=nil.child[1]=null; sz=nil.v=nil.s=0; insert(-INF); insert(INF); } node* newnode(node*p,int key){ pool[sz].parent=p; pool[sz].child[0]=pool[sz].child[1]=null; pool[sz].s=1; pool[sz].v=key; return pool+sz++; } void update(node* x){ if(x != null){ x->s = x->child[0]->s + x->child[1]->s + 1; } } void insert(int key){ if(root==null){ root=newnode(null,key); }else{ node *t=root; while(true){ int d=t->v < key; t->s++; if(t->child[d]==null){ t->child[d] = newnode(t,key); splay(t->child[d],null); return; }else{ t=t->child[d]; } } } } void remove(int value){ int k=find(value); findkth(k-1,null); findkth(k+1,root); root->s--; root->child[1]->s--; root->child[1]->child[0]=null; } void rotate(node *x,int dr){ node *p = x->parent; x->child[dr]->parent=p; p->child[1^dr] = x->child[dr]; x->parent=p->parent; x->child[dr]=p; if(p->parent->child[0]==p){ p->parent->child[0]=x; }else if(p->parent->child[1]==p){ p->parent->child[1]=x; }else root=x; p->parent=x; update(p); update(x); } void splay(node *x, node *y){ while(x->parent != y){ if(x->parent->parent==y){ if(x->parent->child[0]==x)rotate(x,1); else rotate(x,0); }else if(x->parent->parent->child[0] == x->parent){ if(x->parent->child[0]==x){ rotate(x->parent,1); rotate(x,1); }else{ rotate(x,0); rotate(x,1); } }else{ if(x->parent->child[1]==x){ rotate(x->parent,0); rotate(x,0); }else{ rotate(x,1); rotate(x,0); } } } } int find(int key){ node *t=root; int sum=0; while(true){ if(t->v == key){ return sum + t->child[0]->s + 1; }else if(t->v > key){ t = t->child[0]; }else{ sum += t->child[0]->s + 1; t = t->child[1]; } } } int getkth(int k){ findkth(k+1,null); return root->v; } void findkth(int k,node *y){ node *x = root; while(k != x->child[0]->s + 1){ if(k < x->child[0]->s + 1 ){ x = x->child[0]; }else{ k -= x->child[0]->s + 1; x = x->child[1]; } } splay(x,y); }};splaytree tree;struct A{int l,r,i,k;}interval[maxn];int a[maxn];int ans[maxm];bool operator<(const A&a,const A&b){return a.l<b.l||a.l==b.l&&a.r<b.r;}int main(){ int m,n;scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",a+i); } for(int i=0;i<m;i++){scanf("%d %d %d",&interval[i].l,&interval[i].r,&interval[i].k);interval[i].i=i;} std::sort(interval,interval+m); int r=interval[0].r,l=interval[0].l; for(int i=l;i<=r;i++) tree.insert(a[i]); ans[interval[0].i]=tree.getkth(interval[0].k); for(int i=1;i<m;i++){ int R=interval[i].r,L=interval[i].l; if(L>r){ while(l<=r){ tree.remove(a[l++]); } l=L;r=R; while(L<=R){ tree.insert(a[L++]); } }else if(R>r){ while(l<L){ tree.remove(a[l++]); } while(++r<=R){ tree.insert(a[r]); } --r; } else{ while(l<L){ tree.remove(a[l++]); } while(r>R){ tree.remove(a[r--]); } } ans[interval[i].i]=tree.getkth(interval[i].k); } for(int i=0;i<m;i++) printf("%d\n",ans[i]); return 0;}
- poj 2761 Feed the dogs 平衡树,线段树,树状数组
- POJ(2761)Feed the dogs (树状数组+离散化+贪心)
- 划分树 POJ 2761 feed the dogs
- poj 2761 Feed the dogs 划分树
- POJ 2761Feed the dogs 划分树
- POJ 2761 Feed the dogs(主席树)
- POJ 2761 Feed the dogs 树状数组求第k大的数
- POJ 2761 Feed the dogs(划分树)
- POJ 2761 Feed the dogs(Treap名次树+离线处理)
- poj 2104 && 2761 Feed the dogs(划分树)
- POJ 2761 Feed the dogs(主席树)
- POJ-2761-Feed the dogs
- POJ 2761 Feed the dogs
- POJ 2761 Feed the dogs
- POJ 2761 Feed the dogs
- poj 2761 Feed the dogs
- poj 2761 Feed the dogs
- Feed the dogs POJ
- WBS
- The DirectFB screen driver functionality test failed
- 快速排序
- <span>文字居中
- IOS 各种文件路径获取
- poj 2761 Feed the dogs 平衡树,线段树,树状数组
- 对 HTTP 304 的理解
- IOS开发(105)之处理不活动状态
- oracle 闪回查询
- 使用jstack分析cpu消耗过高的问题
- 用SQL将查询出来的多列的值拼接成一个字符串
- galaxy nexus升级包takju-jop40d的boot.img和recovery.img中ramdisk对比
- tcp/ip详解卷1:协议 读书笔记 ICMP:Internet控制报文协议
- VC++ 得到计算机名和用户名 GetComputerName GetUserName