POJ2761--Feed the dogs
来源:互联网 发布:股市软件哪个好 编辑:程序博客网 时间:2024/05/22 13:49
Description
Wind loves pretty dogs very much, and she has n pet dogs. So Jiajia has to feed the dogs every day for Wind. Jiajia loves Wind, but not the dogs, so Jiajia use a special way to feed the dogs. At lunchtime, the dogs will stand on one line, numbered from 1 to n, the leftmost one is 1, the second one is 2, and so on. In each feeding, Jiajia choose an inteval[i,j], select the k-th pretty dog to feed. Of course Jiajia has his own way of deciding the pretty value of each dog. It should be noted that Jiajia do not want to feed any position too much, because it may cause some death of dogs. If so, Wind will be angry and the aftereffect will be serious. Hence any feeding inteval will not contain another completely, though the intervals may intersect with each other.
Your task is to help Jiajia calculate which dog ate the food after each feeding.
Your task is to help Jiajia calculate which dog ate the food after each feeding.
Input
The first line contains n and m, indicates the number of dogs and the number of feedings.
The second line contains n integers, describe the pretty value of each dog from left to right. You should notice that the dog with lower pretty value is prettier.
Each of following m lines contain three integer i,j,k, it means that Jiajia feed the k-th pretty dog in this feeding.
You can assume that n<100001 and m<50001.
The second line contains n integers, describe the pretty value of each dog from left to right. You should notice that the dog with lower pretty value is prettier.
Each of following m lines contain three integer i,j,k, it means that Jiajia feed the k-th pretty dog in this feeding.
You can assume that n<100001 and m<50001.
Output
Output file has m lines. The i-th line should contain the pretty value of the dog who got the food in the i-th feeding.
Sample Input
7 21 5 2 6 3 7 41 5 32 7 1
Sample Output
32
神题啊,线段树,树状数组,Treap,SBT,Splay都可以做。
#include <iostream>#include <cstdio>#include <cstring>#include <cstdlib>#include <algorithm>using namespace std;#define maxn 200080int A[maxn],Ans[maxn];struct Que{int from,to,k,id;}que[maxn>>1];bool cmp(Que a,Que b){if(a.from < b.from)return 1;else if(a.from > b.from)return 0;else return a.to < b.to;}struct Node{Node * ch[2];int r,v,s;/*bool operator < (const Node & a) const{return r < a.r;}*/int cmp(int x) const{if(x == v)return -1;return x < v?0:1;}void maintain(){s = 1;if(ch[0] != NULL)s += ch[0] -> s;if(ch[1] != NULL)s += ch[1] -> s;}}*root;void rotate(Node *& o,int d){Node * k = o -> ch[d^1];o -> ch[d^1] = k -> ch[d];k -> ch[d] = o;o -> maintain();k -> maintain();o = k;}void insert(Node *& o,int x){if(o == NULL){o = new Node();o -> ch[0] = o -> ch[1] = NULL;o -> v = x;o -> r = rand();o -> s = 1;}else {int d = o -> cmp(x);if(d == -1)d = 0;insert(o -> ch[d],x);if(o -> ch[d] -> r > o -> r)rotate(o,d^1);}o -> maintain();}void remove(Node *& o,int x){int d = o -> cmp(x);if(d == -1){Node * tmp = o;if(o -> ch[0] == NULL){o = o -> ch[1];delete tmp;tmp = NULL;}else if(o -> ch[1] == NULL){o = o -> ch[0];delete tmp;tmp = NULL;}else{int d2 = (o -> ch[0] -> r > o -> ch[1] -> r?1:0);rotate(o,d2);remove(o -> ch[d2],x);}}else remove(o -> ch[d],x);if(o != NULL)o -> maintain();}bool find(Node * o,int x){while(o != NULL){int d = o -> cmp(x);if(d == -1)return 1;else o = o -> ch[d];}return 0;}int Rank(Node * o,int x){int ans = 0;while(o){if(o -> v == x){if(o -> ch[0])ans += o -> ch[0] -> s;return ans;}else if(o -> v > x){o = o -> ch[0];}else {if(o -> ch[0])ans += o -> ch[0] -> s;ans++;o = o -> ch[1];}}return ans;}int Kth(Node * o,int k){while(k){if(o -> ch[0]){if(o -> ch[0] ->s >= k) o = o -> ch[0];else if(o -> ch[0] -> s == k-1)return o -> v;else k -= o -> ch[0] -> s + 1,o = o -> ch[1];}else if( k == 1 )return o -> v;else k--,o = o -> ch[1];}}void DeleteTreap(Node *& o){if(o == NULL)return;if(o -> ch[0])DeleteTreap(o -> ch[0]);if(o -> ch[1])DeleteTreap(o -> ch[1]);delete o;o = NULL;}int main(){//freopen("in.txt","r",stdin);int n,m;while(scanf("%d%d",&n,&m)==2){root = NULL;for(int i = 0;i < n;i++){scanf("%d",&A[i]);///insert(root,A[i]);}for(int i = 0;i < m;i++){scanf("%d%d%d",&que[i].from,&que[i].to,&que[i].k);que[i].from--;que[i].to--;que[i].id = i+1;}sort(que,que+m,cmp);for(int i = que[0].from;i <= que[0].to;i++){insert(root,A[i]);}Ans[que[0].id] = Kth(root,que[0].k);int l = que[0].from,r = que[0].to;for(int i = 1;i < m;i++){if(r >= que[i].from){if(l < que[i].from)for(int j = l;j < que[i].from;j++)remove(root,A[j]);else if(l > que[i].from)for(int j = que[i].from;j < l;j++)insert(root,A[j]);if(r < que[i].to)for(int j = r+1;j <= que[i].to;j++)insert(root,A[j]);else if(r > que[i].to)for(int j = que[i].to+1;j <= r;j++)remove(root,A[j]);}else {for(int j = l;j <= r;j++)remove(root,A[j]);for(int j = que[i].from;j <= que[i].to;j++)insert(root,A[j]);}Ans[que[i].id] = Kth(root,que[i].k);l = que[i].from,r = que[i].to;}for(int i = 1;i <= m;i++)printf("%d\n",Ans[i]);DeleteTreap(root);}return 0;}
接下来是线段树做法:
/*首先将数据离散化。然后节点表示这段区间的数有多少个。update函数用来添点删点。二分查找就行。*/#include <iostream>#include <cstring>#include <cstdio>#include <algorithm>using namespace std;#define maxn 100080#define lson id<<1,l,mid#define rson id<<1|1,mid+1,rint X[maxn],XX[maxn],Ans[maxn];struct Que{int from,to,k,id;}que[maxn];bool cmp(Que a,Que b){if(a.from < b.from)return 1;else if(a.from > b.from)return 0;else return a.to < b.to;}struct ST{int l,r,num;}st[maxn<<2];void PushUp(int id){st[id].num = st[id<<1].num + st[id<<1|1].num;}void buildtree(int id,int l,int r){st[id].l = l,st[id].r = r;if(l == r){st[id].num = 0;return;}int mid = (l+r) >> 1;buildtree(lson);buildtree(rson);PushUp(id);}void Update(int id,int pos,int ope){if(st[id].l == st[id].r){st[id].num += ope;return;}if(st[id<<1].r >= pos)Update(id<<1,pos,ope);else Update(id<<1|1,pos,ope);PushUp(id);}int query(int id,int l,int r){if(st[id].l == l && st[id].r == r){return st[id].num;}if(st[id<<1].r >= r){return query(id<<1,l,r);}if(st[id<<1|1].l <= l){return query(id<<1|1,l,r);}return query(id<<1,l,st[id<<1].r) + query(id<<1|1,st[id<<1|1].l,r);}int main(){//freopen("in.txt","r",stdin);int n,m;while(scanf("%d%d",&n,&m)==2){for(int i = 1;i <= n;i++){scanf("%d",&X[i]);}memcpy(XX,X,sizeof(X));sort(X+1,X+n+1);buildtree(1,1,n);for(int i = 0;i < m;i++){scanf("%d%d%d",&que[i].from,&que[i].to,&que[i].k);que[i].id = i+1;}sort(que,que+m,cmp);int l = 1,r = n;for(int i = 1;i <= n;i++){int pos = lower_bound(X+1,X+n+1,XX[i]) - X;Update(1,pos,1);}for(int i = 0;i < m;i++){int u = que[i].from,v = que[i].to;if(r >= u){if(l < que[i].from){for(int j = l;j < que[i].from;j++){int pos = lower_bound(X+1,X+n+1,XX[j]) - X;Update(1,pos,-1);}}if(r > que[i].to){for(int j = que[i].to + 1;j <= r;j++){int pos = lower_bound(X+1,X+n+1,XX[j]) - X;Update(1,pos,-1);}}else if(r < que[i].to){for(int j = r+1;j <= que[i].to;j++){int pos = lower_bound(X+1,X+n+1,XX[j]) - X;Update(1,pos,1);}}}else {for(int j = l;j <= r;j++){int pos = lower_bound(X+1,X+n+1,XX[j])-X;Update(1,pos,-1);}for(int j = que[i].from;j <= que[i].to;j++){int pos = lower_bound(X+1,X+n+1,XX[j])-X;Update(1,pos,1);}}//树已经维护好了,接下来就是二分查找的过程。int ll = 1,rr = n;int k = que[i].k;while(ll < rr){int mid = (ll + rr) >> 1;if(query(1,1,mid) >= k)rr = mid;else ll = mid + 1;}Ans[que[i].id] = X[ll];l = que[i].from,r = que[i].to;}for(int i = 1;i <= m;i++){printf("%d\n",Ans[i]);}}return 0;}
接下来是树状数组。
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define maxn 100080int c[maxn];int X[maxn],XX[maxn],Ans[maxn];int lowbit(int x){return x&(-x);}struct Que{int from,to,k,id;}que[maxn];bool cmp(Que a,Que b){if(a.from < b.from)return 1;else if(a.from > b.from)return 0;else return a.to < b.to;}void update(int x,int add){while(x < maxn){c[x]+=add;x+=lowbit(x);}}int getsum(int x){int sum = 0;while(x > 0){sum += c[x];x -= lowbit(x);}return sum;}int main(){//freopen("in.txt","r",stdin);int n,m;while(scanf("%d%d",&n,&m)==2){for(int i = 1;i <= n;i++)scanf("%d",&X[i]);for(int i = 0;i < m;i++){scanf("%d%d%d",&que[i].from,&que[i].to,&que[i].k);que[i].id = i + 1;}sort(que,que+m,cmp);memset(c,0,sizeof(c));memcpy(XX,X,sizeof(X));sort(X+1,X+n+1);for(int i = 1;i <= n;i++){int pos = lower_bound(X+1,X+n+1,XX[i]) - X;update(pos,1);}int l = 1,r = n;for(int i = 0;i < m;i++){int u = que[i].from,v = que[i].to;if(r >= u){if(l < que[i].from){for(int j = l;j < que[i].from;j++){int pos = lower_bound(X+1,X+n+1,XX[j]) - X;update(pos,-1);}}if(r > que[i].to){for(int j = que[i].to + 1;j <= r;j++){int pos = lower_bound(X+1,X+n+1,XX[j]) - X;update(pos,-1);}}else if(r < que[i].to){for(int j = r+1;j <= que[i].to;j++){int pos = lower_bound(X+1,X+n+1,XX[j]) - X;update(pos,1);}}}else {for(int j = l;j <= r;j++){int pos = lower_bound(X+1,X+n+1,XX[j]) - X;update(pos,-1);}for(int j = que[i].from;j <= que[i].to;j++){int pos = lower_bound(X+1,X+n+1,XX[j]) - X;update(pos,1);}}int ll = 1,rr = n;int k = que[i].k;while(ll < rr){int mid = (ll + rr) >> 1;if(getsum(mid) >= k)rr = mid;else ll = mid + 1;}Ans[que[i].id] = X[ll];l = que[i].from,r = que[i].to;}for(int i = 1;i <= m;i++)printf("%d\n",Ans[i]);}return 0;}
接下来是一点都不SB的SB树:
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define nil 0#define maxn 200080int key[maxn],Left[maxn],Right[maxn],Size[maxn];int A[maxn],Ans[maxn];int root,node;int record;//This is used for the commented Deletestruct Que{int from,to,k,id;}que[maxn];bool cmp(Que a,Que b){if(a.from < b.from)return 1;else if(a.from > b.from)return 0;else return a.to < b.to;}inline void Left_Rotate(int & x){int k = Right[x];Right[x] = Left[k];Left[k] = x;Size[k] = Size[x];Size[x] = Size[Left[x]] + Size[Right[x]] + 1;x = k;}inline void Right_Rotate(int & y){int k = Left[y];Left[y] = Right[k];Right[k] = y;Size[k] = Size[y];Size[y] = Size[Left[y]] + Size[Right[y]] + 1;y = k;}void Maintain(int & T,bool flag);void Insert(int & T,int v){if(T == nil){key[T = ++node] = v;Size[T] = 1;Left[T] = Right[T] = nil;}else {Size[T]++;if(v < key[T])Insert(Left[T],v);elseInsert(Right[T],v);////大于等于就在右边添加。Maintain(T,v >= key[T]);}}int Delete(int & T,int v)///Delete函数我不是很清楚。{if(!T)return 0;Size[T]--;if( (v == key[T]) || (v < key[T] && Left[T] == nil) || (v > key[T] && Right[T] == nil) ){if(Left[T] == nil || Right[T] == nil)////如果只有单支子系,直接用儿子代替他就行了。{int p = T;T = Left[T] + Right[T];return p;}else{//int p = Delete(Left[T],key[T] + 1);int p = Delete(Left[T],v+1);key[T] = key[p];///否则的话,用左支的最大值来替代这个删除点。return p;}}else{if(v < key[T])return Delete(Left[T],v);else return Delete(Right[T],v);}}void Maintain(int & T,bool flag){if(flag == false){if(Size[Left[Left[T]]] > Size[Right[T]])Right_Rotate(T);else if(Size[Right[Left[T]]] > Size[Right[T]]){Left_Rotate(Left[T]);Right_Rotate(T);}else return;}else{if(Size[Right[Right[T]]] > Size[Left[T]])Left_Rotate(T);else if(Size[Left[Right[T]]] > Size[Left[T]]){Right_Rotate(Right[T]);Left_Rotate(T);}else return;}Maintain(Left[T],false);Maintain(Right[T],true);Maintain(T,false);Maintain(T,true);}int Search(int x,int k)///寻找=k的那个数{if(x == nil || k == key[x])return x;if(k < key[x])return Search(Left[x],k);else return Search(Right[x],k);}int Select(int T,int k)///选择第k小的数{int r = 1 + Size[Left[T]];if(k == r)return key[T];else if(k < r)return Select(Left[T],k);else return Select(Right[T],k - r);}int Succ(int T,int k)///找后继{if(T == nil)return k;if(key[T] <= k)return Succ(Right[T],k);else {int r = Succ(Left[T],k);if(r == k)return key[T];else return r;}}int Pred(int T,int k)///找前驱{if(T == nil)return k;if(key[T] >= k)return Pred(Left[T],k);else{int r = Pred(Right[T],k);if(r == k)return key[T];else return r;}}int Rank(int T,int k)///k在这颗树中排第几大{if(T == nil)return 1;if(key[T] >= k)return Rank(Left[T],k);else return Size[Left[T]] + Rank(Right[T],k) + 1;}int main(){//freopen("in.txt","r",stdin);int n,m;while(scanf("%d%d",&n,&m)==2){for(int i = 1;i <= n;i++)scanf("%d",&A[i]);for(int i = 0;i < m;i++){int u,v,k;scanf("%d%d%d",&u,&v,&k);que[i].from = u,que[i].to = v,que[i].k = k,que[i].id = i+1;}memset(Size,0,sizeof(Size));sort(que,que+m,cmp);root = node = 0;for(int i = 1;i <= n;i++)Insert(root,A[i]);int l = 1,r = n;for(int i = 0;i < m;i++){int u = que[i].from,v = que[i].to,k = que[i].k;if(r >= u){if(l < u){for(int j = l;j < u;j++)Delete(root,A[j]);}if(r < v){for(int j = r+1;j <= v;j++)Insert(root,A[j]);}else if(r > v){for(int j = v+1;j <= r;j++)Delete(root,A[j]);}}else {for(int j = l;j <= r;j++)Delete(root,A[j]);for(int j = u;j <= v;j++)Insert(root,A[j]);}Ans[que[i].id] = Select(root,k);l = u,r = v;}for(int i = 1;i <= m;i++)printf("%d\n",Ans[i]);}return 0;}
接下来是专门解决区间第K小的主席树:
#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#include <queue>#include <string>#include <string>using namespace std;#define maxn 100080#define maxm 5600800int T[maxn],key[maxn],a[maxn];int c[maxm],lson[maxm],rson[maxm];int n,m,tot;void Hash_init(){tot = 0;for(int i = 1;i <= n;i++)a[i] = key[i];sort(key+1,key+n+1);}int Hash(int k){return lower_bound(key+1,key+n+1,k) - key;}int build(int l,int r){int root = tot++;c[root] = 0;if(l != r){int mid = (l+r) >> 1;lson[root] = build(l,mid);rson[root] = build(mid+1,r);}return root;}int Update(int root,int pos,int val){int newnode = tot++,tmp = newnode;c[newnode] = c[root] + val;int l = 1,r = n;while(l < r){int mid = (l+r) >> 1;if(pos <= mid){lson[newnode] = tot++;rson[newnode] = rson[root];newnode = lson[newnode];root = lson[root];r = mid;}else{rson[newnode] = tot++;lson[newnode] = lson[root];newnode = rson[newnode];root = rson[root];l = mid + 1;}c[newnode] = c[root] + val;}return tmp;}int query(int left_root,int right_root,int k){int l = 1,r = n;while(l < r){int mid = (l+r) >> 1;if(c[lson[left_root]] - c[lson[right_root]] >= k){r = mid;left_root = lson[left_root];right_root = lson[right_root];}else {l = mid + 1;k -= c[lson[left_root]] - c[lson[right_root]];left_root = rson[left_root];right_root = rson[right_root];}}return l;}int main(){while(scanf("%d%d",&n,&m)==2){for(int i = 1;i <= n;i++)scanf("%d",&key[i]);Hash_init();T[n+1] = build(1,n);for(int i = n;i >= 1;i--){int pos = Hash(a[i]);T[i] = Update(T[i+1],pos,1);}while(m--){int u,v,k;scanf("%d%d%d",&u,&v,&k);printf("%d\n",key[query(T[u],T[v+1],k)]);}}return 0;}
- [poj2761]Feed the dogs
- POJ2761 Feed the dogs
- POJ2761 Feed the dogs
- POJ2761--Feed the dogs
- poj2761 Feed the dogs
- 【poj2761】 Feed the dogs
- POJ2761 Feed the dogs(treap)
- [Treap] poj2761 Feed the dogs
- poj2761 Feed the dogs【解法一】
- poj2761 Feed the dogs【解法二】
- 【主席树】poj2104 K-th Number && poj2761 Feed the dogs
- [POJ2104] K-th Number/[POJ2761] Feed the dogs
- POJ2761[Feed the dogs ] 不带修改主席树
- poj2761——Feed the dogs(划分树或SBT)
- 划分树学习笔记——NOJ[1458] Teemo,POJ2761——Feed the dogs
- Feed the dogs POJ
- PKU 2761 Feed the dogs
- POJ-2761-Feed the dogs
- 最新隐藏进程 RING3实现方式:hook ZwQuerySystemInformation 隐藏进程 在XP里测试通过
- SSH环境中如何得到LocalSessionFactoryBean
- Android视图绘制流程完全解析,带你一步步深入了解View(二)
- 逆向编程培训(第二课)
- vim的交换文件
- POJ2761--Feed the dogs
- CLHLock的实际应用
- vim用autocmd命令自动插入最后修改日期
- 片上总线Wishbone 学习(三)Wishbone互联的类型
- QTP 解析外部的XML的环境变量文件
- AWK
- 08-EasyUI_datagrid
- Spring3.0 —— 表达式语言(SpEL)
- SHELL 十三问