Poj2761-Feed the dogs(伸展树求名次)

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.

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.

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 2
1 5 2 6 3 7 4
1 5 3
2 7 1

Sample Output

3
2
题意:查询一段区间的第k大值,而且题目保证查询区间是不存在包含关系。

解析:因为不存在包含关系,所以直接离线排序,向右插入元素,向右删除元素。利用treap树实现名次树的功能。

代码

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
using namespace std;
const int INF=1e9+7;
const int maxn=100005;
int A[maxn],cnt;  //A数组保存数,cnt是节点标号,我是用数组模拟的
struct treap
{
    treap* son[2];  //左右儿子
    int v,s,r;
    treap(){ v=s=r=0; son[0]=son[1]=NULL; }
    treap(int nv,int nr);
    int rk(){ return son[0]->s+1; }  //排名,第几个数
    int cmp(int k)  //比较,如果相等返回-1,小于返回0,大于1
    {
        if(k==v) return -1;
        return k<v?0:1;
    }
    void pushup(){ s=son[0]->s+son[1]->s+1; }  //更新大小
}null,tr[maxn];
treap::treap(int nv,int nr)
{
    v=nv; r=nr;
    s=1;
    son[0]=son[1]=&null;
}
treap* NewNode(int x,int r)//建新节点
{
    tr[cnt]=treap(x,r);
    return tr+cnt++;
}
struct splaytree
{
    int Size;
    treap* root;
    splaytree(){ Size=0; root=&null; }
    void Rotate(treap* &t,int d)  //翻转操作
    {
        treap* p=t->son[d^1];
        t->son[d^1]=p->son[d];
        p->son[d]=t;
        t->pushup();  //要更新
        t=p;
        t->pushup();
    }
    void Insert(treap* &t,int x,int r) //插入
    {
        if(t==&null) //插入
        {
            t=NewNode(x,r); //申请新节点
            return;
        }
        int d=t->cmp(x);
        if(d==-1) d=1; //往右边走
        Insert(t->son[d],x,r);
        if(t->son[d]->r > t->r) Rotate(t,d^1); //旋转
        t->pushup();
    }
    void Remove(treap* &t,int x) //删除
    {
        int d=t->cmp(x);
        if(d==-1)
        {
            if(t->son[0]==&null) t=t->son[1];
            else if(t->son[1]==&null) t=t->son[0];
            else
            {
                int d2=(t->son[0]->r > t->son[1]->r ? 1: 0);
                Rotate(t,d2);
                Remove(t->son[d2],x);
            }
        }
        else Remove(t->son[d],x);
        if(t!=&null) t->pushup();
    }
    int Query(treap* &t,int kth) //查询
    {
        if(t==&null||kth<=0||kth>t->s) return -1;
        int a=t->rk();
        if(kth==a) return t->v;
        else if(kth<a) return Query(t->son[0],kth);
        else return Query(t->son[1],kth-a);
    }
};
int N,M;
struct Ques
{
    int x,y,k,id;
    Ques(int x=0,int y=0,int k=0,int id=0):x(x),y(y),k(k),id(id){}
    bool operator < (const Ques& t) const
    {
        if(x!=t.x) return x<t.x;
        return y<t.y;
    }
}q[maxn];
int ans[maxn];
int main()
{
    scanf("%d%d",&N,&M);
        splaytree spt; cnt=0;
        for(int i=1;i<=N;i++) scanf("%d",&A[i]);
        int x,y,k;
        for(int i=0;i<M;i++) //输入
        {
            scanf("%d%d%d",&x,&y,&k);
            q[i]=Ques(x,y,k,i);
        }
        sort(q,q+M); //排序
        int f=1,r=1;
        for(int i=0;i<M;i++)
        {
            Ques& t=q[i];
            int x=t.x,y=t.y,k=t.k;
            for(;f<x;f++) if(f<r) spt.Remove(spt.root,A[f]);
            if(r<f) r=f;
            for(;r<=y;r++) spt.Insert(spt.root,A[r],rand());
            ans[t.id]=spt.Query(spt.root,k);  //保存答案
        }
        for(int i=0;i<M;i++) printf("%d\n",ans[i]);
    return 0;
}

时间: 2024-10-11 05:45:26

Poj2761-Feed the dogs(伸展树求名次)的相关文章

POJ2761 Feed the dogs

Time Limit: 6000MS   Memory Limit: 65536KB   64bit IO Format: %lld & %llu 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 sp

[POJ2761]Feed the dogs(静态区间第k小,主席树)

题目链接:http://poj.org/problem?id=2761 题意:如题 主席树只能用模版,好菜. 1 /* 2 ━━━━━┒ギリギリ♂ eye! 3 ┓┏┓┏┓┃キリキリ♂ mind! 4 ┛┗┛┗┛┃\○/ 5 ┓┏┓┏┓┃ / 6 ┛┗┛┗┛┃ノ) 7 ┓┏┓┏┓┃ 8 ┛┗┛┗┛┃ 9 ┓┏┓┏┓┃ 10 ┛┗┛┗┛┃ 11 ┓┏┓┏┓┃ 12 ┛┗┛┗┛┃ 13 ┓┏┓┏┓┃ 14 ┃┃┃┃┃┃ 15 ┻┻┻┻┻┻ 16 */ 17 #include <algorithm>

【莫队算法】【权值分块】poj2104 K-th Number / poj2761 Feed the dogs

先用莫队算法保证在询问之间转移的复杂度,每次转移都需要进行O(sqrt(m))次插入和删除,权值分块的插入/删除是O(1)的. 然后询问的时候用权值分块查询区间k小值,每次是O(sqrt(n))的. 所以总共的复杂度是O(m*(sqrt(n)+sqrt(m)))的. 常数极小. 别的按权值维护的数据结构无法做到O(1)地插入删除. poj2104 的输出优化 别忘了处理负数. 完爆主席树,这份代码目前在 poj2761 上 Rank1. Rank Run ID User Memory Time

[POJ2761] Feed the dogs (Treap)

题目链接:http://poj.org/problem?id=2761 题目大意:给你n个数,m次查询,m次查询分别是a,b,k,查询下表从a到b的第k小元素是哪个.这m个区间不会互相包含. Treap,自己学着写了个板子,留贴备用. 离线操作,将区间移动之,删除旧的添加新的. #include <cstdio> #include <cstring> #include <algorithm> #include <vector> #include <ma

Splay树(区间第k小)——POJ 2761 Feed the dogs

对应POJ题目:点击打开链接 Feed the dogs Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 16655   Accepted: 5203 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 Win

POJ 2761 Feed the dogs (主席树)(K-th 值)

                                                            Feed the dogs Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 20634   Accepted: 6494 Description Wind loves pretty dogs very much, and she has n pet dogs. So Jiajia has to feed

【POJ2761】【区间第k大】Feed the dogs(吐槽)

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,

poj2761 feed the dog

题目链接:http://poj.org/problem?id=2761 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 lunchti

伸展树整理

伸展树 1.在伸展树上的一般操作都基于伸展操作:假设想要对一个二叉查找树执行一系列的查找操作,为了使整个查找时间更小,被查频率高的那些条目就应当经常处于靠近树根的位置.因此,在每次查找之后对树进行重构,把被查找的条目搬移到离树根近一些的地方.伸展树应运而生.伸展树是一种自调整形式的二叉查找树,它会沿着从某个节点到树根之间的路径,通过一系列的旋转把这个节点搬移到树根去. 2.操作 (1)伸展操作 伸展操作Splay(x,S)是在保持伸展树有序性的前提下,通过一系列旋转将伸展树S中的元素x调整至树的