[SBT]POJ 2761 Feed the dogs

原创 2012年03月29日 13:16:44

题目链接:http://poj.org/problem?id=2761

题意:给定一个序列,有N个数,给定M个询问,询问的形式为 a b c ,询问区间[a,b]内第c小的数。

解题方法:一次性读入所有的询问,然后把询问进行排序,排序的顺序为终点小的在前,终点一样,起点大的在前,然后对排序后的每个询问进行处理,每次保证SBT中只有区间[a,b]的数(用插入和删除操作来保证),然后查询第K小。

总结:注意旋转操作调整size域的顺序。 不能搞反。

代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct KEY
{
   int wgt,num;
   KEY(int w=0,int n=0):wgt(w),num(n){}
   bool operator < (const KEY &k) const
   {
        if(wgt!=k.wgt)return wgt<k.wgt;
        return num<k.num;
   }
   bool operator == (const KEY &k) const
   {
        return wgt==k.wgt&&num==k.num;
   }
};
const int MAXN = 100010;
struct SBT
{
    int l[MAXN],r[MAXN],pool[MAXN],size[MAXN],TOP,NODE,ROOT;
    KEY Key[MAXN];
    void init()
    {
         TOP = NODE = ROOT = 0;
         size[0] = l[0] = r[0] = 0;
    }
    int newnode(KEY k)
   {
        int node;
        if(TOP)node = pool[TOP--];
        else node = ++NODE;
        Key[node] = k;
        size[node] = 1;
        l[node] = r[node] = 0;
        return node;
   }
   void delnode(int x)
   {
        pool[++TOP] = x;
        Key[x].wgt = Key[x].num = size[x] = l[x] = r[x] = 0;
   }
    void left_rotate(int &p)
    {
         int x = r[p];
         r[p] = l[x];
         l[x] = p;
         size[x] = size[p];
         size[p] = size[l[p]]+size[r[p]]+1;
         p = x;
    }
    void right_rotate(int &p)
    {
         int x = l[p];
         l[p] = r[x];
         r[x] = p;
         size[x] = size[p];
         size[p] = size[l[p]]+size[r[p]]+1;
         p = x;
    }
    void Maintain(int &p,bool flag)
    {
         if(flag==0)
         {
             if(size[l[l[p]]]>size[r[p]])right_rotate(p);
             else if(size[r[l[p]]]>size[r[p]])
             {
                 left_rotate(l[p]);
                 right_rotate(p);
             }
             else return;
         }
         else
         {
             if(size[r[r[p]]]>size[l[p]])left_rotate(p);
             else if(size[l[r[p]]]>size[l[p]])
             {
                  right_rotate(r[p]);
                  left_rotate(p);
             }
             else return;
         }
         Maintain(l[p],0);
         Maintain(r[p],1);
         Maintain(p,1);
         Maintain(p,0);
    }
    void insert(int &p,KEY k)
    {
         if(!p)
         {
             p = newnode(k);
             return;
         }
         if(k<Key[p])insert(l[p],k);
         else insert(r[p],k);
         size[p] = size[l[p]]+size[r[p]]+1;
         Maintain(p,!(k<Key[p]));
    }
    int findmin(int p)
    {
        if(l[p])return findmin(l[p]);
        else return p;
    }
    void remove(int &p,KEY k)
    {
         if(p)
         {
             if(k==Key[p])
             {
                 if(!l[p])
                 {
                     int x = p;
                     p = r[p];
                     delnode(x);
                 }
                 else if(!r[p])
                 {
                     int x = p;
                     p = l[p];
                     delnode(x);
                 }
                 else 
                 {
                     int x = findmin(r[p]);
                     Key[p] = Key[x];
                     remove(r[p],Key[x]);
                 }
             }
             else if(k<Key[p])remove(l[p],k);
             else remove(r[p],k);
             if(p)
             {
                  size[p] = size[l[p]]+size[r[p]]+1;
             }
         }
    }
    int Select(int p,int k)
    {
        int rank = size[l[p]]+1;
        if(k==rank)return p;
        else if(k<rank)return Select(l[p],k);
        return Select(r[p],k-rank);
    }
    void print(int p)
    {
        if(!p)return ;
        print(l[p]);
        cout<<size[p]<<" "<<Key[p].wgt<<" "<<l[p]<<" "<<r[p]<<" "<<p<<" "<<(size[l[p]]+size[r[p]]+1)<<endl;
        print(r[p]);
    }
}sbt;
int arr[MAXN],res[50010];
struct Range
{
    int a,b,c,num;
    bool operator < (const Range &r) const
    {
         if(b!=r.b)return b<r.b;
         else return a>r.a;
    }
}R[50010];

int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
         int a,b;sbt.init();
         for(int i=1;i<=n;i++)
         {
             scanf("%d",&arr[i]);
         }
         for(int i=1;i<=m;i++)
         {
             scanf("%d%d%d",&R[i].a,&R[i].b,&R[i].c);
             R[i].num = i;
         }
         sort(R+1,R+m+1);a = R[1].a; b = R[1].b;
         for(int i=a;i<=b;i++)
         {
             sbt.insert(sbt.ROOT,KEY(arr[i],i));
         }
         res[R[1].num] = sbt.Key[sbt.Select(sbt.ROOT,R[1].c)].wgt;
         for(int i=2;i<=m;i++)
         {
             if(R[i].a<a)
             {
                 for(int j=R[i].a;j<a;j++)
                 {
                     sbt.insert(sbt.ROOT,KEY(arr[j],j));
                 }
                 for(int j=b+1;j<=R[i].b;j++)
                 {
                     sbt.insert(sbt.ROOT,KEY(arr[j],j));
                 }
             }
             else if(R[i].a<b)
             {
                 for(int j=a;j<R[i].a;j++){
                     sbt.remove(sbt.ROOT,KEY(arr[j],j));
                 }
                 for(int j=b+1;j<=R[i].b;j++){
                     sbt.insert(sbt.ROOT,KEY(arr[j],j));
                 }
             }
             else 
             {
                 for(int j=a;j<=b;j++){
                     sbt.remove(sbt.ROOT,KEY(arr[j],j));
                 }
                 for(int j=R[i].a;j<=R[i].b;j++){
                     sbt.insert(sbt.ROOT,KEY(arr[j],j)); 
                 }
             }
             a = R[i].a, b = R[i].b;
             res[R[i].num] = sbt.Key[sbt.Select(sbt.ROOT,R[i].c)].wgt;
         }
         for(int i=1;i<=m;i++)printf("%d\n",res[i]);
    }
    return 0;
}


 

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

poj 2761 Feed the dogs SBT

Feed the dogs 查询一个区间上第k大的数,基本思路就是在sbt里只存要查询的区间上的数 先把要查询的区间按起点从小到大排序,这样就可以利用前一个区间上的数,i和i-1有重叠,那么就没有必要...

[poj2761]Feed the dogs

treap 区间第k大

poj2761 Feed the dogs【解法一】

离散化+树状数组+二分

poj 2761 Feed the dogs

题意:给出n( 解:因为两两查询区间互不包含,所以按L从小到大排序,则必有Li       所以对于每一个查询,删除当前treap中当前查询不包含的点,插入当前treap中当前查询未插入的点    ...

POJ 2761 Feed the dogs

题目大意:         Wind爱狗,并且有n条狗(n         喂食会有m次(m 使用规模平衡二叉树SBT(Size Balanced Tree): 注释代码: 无注释代码: 单词解释...

POJ 2761-Feed the dogs(划分树)求区间内第k小的数

Feed the dogs Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 17679 ...

poj 2761 Feed the dogs 离线treap

Language: Default Feed the dogs Time Limit: 6000MS   Memory Limit: 65536K Total ...

POJ2761[Feed the dogs ] 不带修改主席树

POJ2761 主席树

[统计] poj 2761 Feed the dogs

/** [统计] poj 2761 Feed the dogs 题意: n个数,m个查询,每次查询[l,r]区间里第k小的数。(需要离散化) 题目保证了区间不会相互包含,可以按L排个序。 然后对于每个...

poj 2761 Feed the dogs(treap+离线)

题目链接:http://poj.org/problem?id=2761 思路:求区间第k小的树,题目中有一个关键的条件即没有一个区间能够包含另外一个区间,也就是说如果[ai,bi],[aj,bj]两...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)