poj 2761 Feed the dogs (treap树)
2016-08-13 18:17
441 查看
/************************************************************* 题目: Feed the dogs(poj 2761) 链接: http://poj.org/problem?id=2761 题意: 给一个数列,在给一些区间,求这些区间第k小的值,这些 区间没有包含关系,也就是说如果La>Lb那么Ra>Rb; 算法: treap树 思路: 由于这些区间没有包含关系,把这些区间排序后从左边 开始计算,每计算一个区间把前面多余数删除,这样每 个点只要插入和删除一次就可以了。 **************************************************************/ #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; const int mx=1000005; struct S { int l, r; int di,k; }; S s[mx]; int a[mx]; int ans[mx]; int n,m; bool com(S a,S b) { if (a.l==b.l) return a.r<b.r; return a.l<b.l; } typedef struct Node ///节点的结构体 { Node *l,*r; int val,pri; ///节点的值和优先级 int sz; ///节点子树的节点数 Node(int x) ///初始化节点 { l=r=NULL; val=x; pri=rand(); sz=1; } }Node; Node *root; int Tsize(Node *T) ///计算子树的叶子节点 { if (T==NULL) return 0; return T->sz; } Node *L_rotate(Node *T) ///右节点的优先级大于当前节点的优先级,进行左旋转 { Node *A=T->r; ///A表示有节点 T->r=A->l; A->l=T; A->sz-T->sz; ///交换后A变成当前节点,所以它的子树的节点数等于原来节点的节点数 T->sz=Tsize(T->l)+Tsize(T->r)+1; return A; } Node *R_rotate(Node *T) ///左节点的优先级大于当前节点的优先级,进行右旋转 { Node *A=T->l; T->l=A->r; A->r=T; A->sz=T->sz; T->sz=Tsize(T->l)+Tsize(T->r)+1; return A; } void inser(Node *&T,int val) ///插入函数,和二叉排序树差不多 { if (T==NULL) { T=new Node(val); return ; } if (T->val>=val) { inser(T->l,val); if ((T->l->pri)<(T->pri)) T=R_rotate(T); ///优先级比较,并旋转 } else { inser(T->r,val); if ((T->r->pri)<(T->pri)) T=L_rotate(T); } T->sz=Tsize(T->l)+Tsize(T->r)+1; } void Delete(Node *&T,int val) ///删除函数 { if (T->val>val) Delete(T->l,val); else if (T->val<val) Delete(T->r,val); else { if (T->l==NULL&&T->r==NULL) T=NULL; ///左右节点都为空 else if (T->r==NULL) T=T->l; ///右节点为空 else if(T->l==NULL) T=T->r; ///左节点为空 else ///左右都不空 { if (T->l->pri<T->r->pri) ///左节点优先级小于右边 { ///右旋转,并向右子树删除 T=R_rotate(T); ///应为有旋转后,要删除的节点到有子树去了 Delete(T->r,val); } else { T=L_rotate(T); Delete(T->l,val); } } } if (T!=NULL) { T->sz=Tsize(T->l)+Tsize(T->r)+1; } } int Find(Node *T,int k) ///查找第k小的树 { int temp=Tsize(T->l)+1; ///temp小于等于T->val数的个数 if (temp==k) return T->val; if (temp>k) return Find(T->l,k); return Find(T->r,k-temp); } void solve() { sort(s+1,s+m+1,com); s[0].l=-1; s[0].r=-2; for (int i=1;i<=m;i++) { for (int j=s[i-1].l;j<=min(s[i-1].r,s[i].l-1);j++) Delete(root,a[j]); ///删除比要计算区间多的数 for (int j=max(s[i-1].r+1,s[i].l);j<=s[i].r;j++) inser(root,a[j]); ///插入该区间剩下的数 ans[s[i].di]=Find(root,s[i].k); } for (int j=s[m].l;j<=s[m].r;j++) Delete(root,a[j]); } int main() { scanf("%d%d",&n,&m); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1;i<=m;i++) { int l,r; scanf("%d%d%d",&l,&r,&s[i].k); s[i].l=min(l,r); s[i].r=max(l,r); s[i].di=i; } root=NULL; solve(); for (int i=1;i<=m;i++) printf("%d\n",ans[i]); }
相关文章推荐
- poj 2761 Feed the dogs (Treap+离线处理)
- 【数据结构】【treap】【poj 2761】Feed the dogs
- POJ 2761 Feed the dogs 基础Treap
- POJ 2761 Feed the dogs(Treap名次树+离线处理)
- POJ2761 Feed the dogs(treap)
- POJ 2761 Feed the dogs(Treap求第K小数)
- poj 2761 Feed the dogs(treap+离线)
- POJ 2761 Feed the dogs [离线+treap]
- poj 2761 Feed the dogs 离线treap
- POJ-2761-Feed the dogs
- 划分树 POJ 2761 feed the dogs
- poj 2104 K-th Number && poj 2761 Feed the dogs
- [SBT]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 (树状数组+离散化+贪心)
- hdu 2665 Kth number || poj 2761 Feed the dogs || poj 2104 K-th Number
- POJ 2761 Feed the dogs
- poj 2104 && 2761 Feed the dogs(划分树)