【描述】

cjBBteam拥有一个很大的野生动物园。这个动物园坐落在一个狭长的山谷内,这个区域从南到北被划分成N个区域,每个区域都饲养着一头狮子。这些狮子从北到南编号为1,2,3,…,N。每头狮子都有一个觅食能力值Ai,Ai越小觅食能力越强。饲养员cmdButtons决定对狮子进行M次投喂,每次投喂都选择一个区间[I,J],从中选取觅食能力值第K强的狮子进行投喂。值得注意的是,cmdButtons不愿意对某些区域进行过多的投喂,他认为这样有悖公平。因此cmdButtons的投喂区间是互不包含的。你的任务就是算出每次投喂后,食物被哪头狮子吃掉了。

【输入格式】

输入第一行有两个数N和M。此后一行有N个数,从南到北描述狮子的觅食能力值。此后M行,每行描述一次投喂。第t+2的三个数I,J,K表示在第t次投喂中,cmdButtons选择了区间[I,J]内觅食能力值第K强的狮子进行投喂。

【输出格式】

输出有M行,每行一个整数。第i行的整数表示在第i次投喂中吃到食物的狮子的觅食能力值。

【样例输入】


【样例输出】


【分析】

平衡树解法:

由题目给出的区间互相不包含可以得出,若将每次询问的区间按照起始区域进行排序,那一定是一段接一段,只有可能是两种情况:

下一段的左端与上一段的右端不相交或者相交。

这两种情况都是前面的数据与后面的数据互不影响,因此将区间排序之后,对于每一个区间,删除掉前面多余的,插入后面不够的,使平衡树中仅留下该区间中的数据,然后直接找第k小即可。

SBT可解。

 /* ***********************************************
MYID : Chen Fan
LANG : G++
PROG : VIJOS1081
************************************************ */ #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; #define MAXN 100010 int sons[MAXN][];
int size[MAXN],data[MAXN];
int sbt=,sbttail=; void rotate(int &t,int w) //rotate(&node,0/1)
{
int k=sons[t][-w];
if (!k) return ;
sons[t][-w]=sons[k][w];
sons[k][w]=t;
size[k]=size[t];
size[t]=size[sons[t][]]+size[sons[t][]]+;
t=k;
} void maintain(int& t,bool flag) //maintain(&node,flag)
{
if (!t) return ;
if (!flag)
if (size[sons[sons[t][]][]]>size[sons[t][]]) rotate(t,);
else if (size[sons[sons[t][]][]]>size[sons[t][]])
{
rotate(sons[t][],);
rotate(t,);
} else return ;
else
if (size[sons[sons[t][]][]]>size[sons[t][]]) rotate(t,);
else if (size[sons[sons[t][]][]]>size[sons[t][]])
{
rotate(sons[t][],);
rotate(t,);
} else return ; maintain(sons[t][],false);
maintain(sons[t][],true);
maintain(t,false);
maintain(t,true);
} void insert(int& t,int v) //insert(&root,0,value)
{
if (!t)
{
sbttail++;
data[sbttail]=v;
size[sbttail]=;
sons[sbttail][]=;
sons[sbttail][]=;
t=sbttail;
} else
{
size[t]++;
if (v<data[t]) insert(sons[t][],v);
else insert(sons[t][],v);
maintain(t,v>=data[t]);
}
} int del(int& t,int v) //del(&root,key)
{
size[t]--;
if (v==data[t]||(v<data[t]&&sons[t][]==)||(v>data[t]&&sons[t][]==))
{
int ret=data[t];
if (sons[t][]==||sons[t][]==) t=sons[t][]+sons[t][];
else data[t]=del(sons[t][],data[t]+);
return ret;
} else
if (v<data[t]) return del(sons[t][],v);
else return del(sons[t][],v);
} int select(int t,int k)
{
if (k==size[sons[t][]]+) return t;
if (k<=size[sons[t][]]) return select(sons[t][],k);
else return select(sons[t][],k--size[sons[t][]]);
} typedef struct nod
{
int i,l,r,k;
} node;
node d[]; bool op(node a,node b)
{
if (a.l==b.l) return a.r<b.r;
else return a.l<b.l;
} int a[MAXN]; typedef struct nod1
{
int i,ans;
} node1;
node1 out[]; bool op1(node1 a,node1 b)
{
return a.i<b.i;
} int main()
{
freopen("1.txt","r",stdin); sbt=,sbttail=;
int n,m;
scanf("%d%d",&n,&m);
for (int i=;i<=n;i++) scanf("%d",&a[i]);
for (int i=;i<=m;i++)
{
scanf("%d%d%d",&d[i].l,&d[i].r,&d[i].k);
d[i].i=i;
}
sort(&d[],&d[m+],op); int l=,r=;
for (int i=;i<=m;i++)
{
if (r<d[i].l)
{
sbt=;
sbttail=;
for (int j=d[i].l;j<=d[i].r;j++) insert(sbt,a[j]);
} else
{
for (int j=l;j<d[i].l;j++) del(sbt,a[j]);
for (int j=r+;j<=d[i].r;j++) insert(sbt,a[j]);
}
l=d[i].l;
r=d[i].r;
int temp=select(sbt,d[i].k); out[i].i=d[i].i;
out[i].ans=data[temp];
} sort(&out[],&out[m+],op1);
for (int i=;i<=m;i++) printf("%d\n",out[i].ans); return ;
}

划分树解法:

划分树是一种类似快排的数据结构,可以快速在O(logn)的时间内直接求出某个区间内的k值。

然后本题就是......一棵裸的划分树,直接套即可

。。。。。。最后的结果是,不知道为什么比SBT要慢很多,直观的感觉上划分树没有多余的删除操作,应该会快很多的

 /* ***********************************************
MYID : Chen Fan
LANG : G++
PROG : VIJOS1081_SortTree
************************************************ */ #include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; #define MAXN 100010 int a[MAXN],dp[][MAXN],tree[][MAXN]; void maketree(int c,int l,int r)
{
int mid=(l+r)/,ls=l,rs=mid+,num=; for (int i=mid;i>=l&&a[i]==a[mid];i--) num++;
for (int i=l;i<=r;i++)
{
if (i==l) dp[c][i]=;
else dp[c][i]=dp[c][i-]; if (tree[c][i]<a[mid])
{
dp[c][i]++;
tree[c+][ls]=tree[c][i];
ls++;
} else
if (tree[c][i]>a[mid])
{
tree[c+][rs]=tree[c][i];
rs++;
} else
{
if (num)
{
num--;
dp[c][i]++;
tree[c+][ls]=tree[c][i];
ls++;
} else
{
tree[c+][rs]=tree[c][i];
rs++;
}
}
} if (l==r) return ;
maketree(c+,l,mid);
maketree(c+,mid+,r);
} int query(int c,int l,int r,int ql,int qr,int k)
{
if (l==r) return tree[c][l];
int s,ss,mid=(l+r)/; if (l==ql)
{
s=;
ss=dp[c][qr];
} else
{
s=dp[c][ql-];
ss=dp[c][qr]-s;
}
if (k<=ss) return query(c+,l,mid,l+s,l+s+ss-,k);
else return query(c+,mid+,r,mid-l++ql-s,mid-l++qr-s-ss,k-ss);
} int main()
{
//freopen("1.in","r",stdin);
//freopen("zoo8.in","r",stdin);
//freopen("1.out","w",stdout); int n,m;
scanf("%d%d",&n,&m); for (int i=;i<=n;i++)
{
scanf("%d",&a[i]);
tree[][i]=a[i];
}
sort(&a[],&a[n+]); maketree(,,n); for (int i=;i<=m;i++)
{
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",query(,,n,l,r,k));
} return ;
}

VIJOS P1081 野生动物园 SBT、划分树模板的更多相关文章

  1. vijos 1081 野生动物园 函数式线段树

    描述 cjBBteam拥有一个很大的野生动物园.这个动物园坐落在一个狭长的山谷内,这个区域从南到北被划分成N个区域,每个区域都饲养着一头狮子.这些狮子从北到南编号为1,2,3,…,N.每头狮子都有一个 ...

  2. hdu 2665 Kth number(划分树模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=2665 [ poj 2104 2761 ]  改变一下输入就可以过 http://poj.org/problem? ...

  3. poj2104(划分树模板)

    poj2104 题意 给出一个序列,每次查询一个区间,要求告诉这个区间排序后的第k个数. 分析 划分树模板,O(mlogn). 建树.根据排序之后的数组,对于一个区间,找到中点的数,将整个区间分为左右 ...

  4. poj2104(划分树模板)

    poj2104 题意 给出一个序列,每次查询一个区间,要求告诉这个区间排序后的第k个数. 分析 划分树模板,O(mlogn). 建树.根据排序之后的数组,对于一个区间,找到中点的数,将整个区间分为左右 ...

  5. HDU-3743 Minimum Sum,划分树模板

    Minimum Sum 被这个题坑了一下午,原来只需找一个最中间的数即可,我以为是平均数. 题意:找一个数使得这个数和区间内所有数的差的绝对值最小.输出最小值. 开始用线段树来了一发果断T了,然后各种 ...

  6. poj 2104 (划分树模板)

    Description You are working for Macrohard company in data structures department. After failing your ...

  7. POJ2104 K-th Number 划分树 模板题啊

    /*Source Code Problem: 2104 User: 96655 Memory: 14808K Time: 1282MS Language: G++ Result: Accepted S ...

  8. hdu 2665 划分树模板题(可作为模板)

    Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  9. hdu2665 && poj2104划分树

    K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 47066   Accepted: 15743 Ca ...

随机推荐

  1. AS3.0杂记——Dictionary、Object与Array

    来源:http://blog.csdn.net/m_leonwang/article/details/8811829 Object.Array与Dictionary都是关联数组,就是用“键”来索引存储 ...

  2. orderby与groupby区别

    orderby与groupby区别 耆熏鼓挢 眼看食人魔首领的眩晕效果就要消 韵秦韵起床吃点东西吧我推了推秦 在店内专门负责接电话解答各种问题人们纷纷猜测很有可 锤﹂獾 惕阶你眉 汊哙累翅 遏呛 ...

  3. k个区间相交的段落数 Educational Codeforces Round 4 D

    http://codeforces.com/contest/612/problem/D 题目大意:给你n个区间,这n个区间会有相交的部分,如果一个区间相交的部分>=k,那么就把这个区间记录下来. ...

  4. Linux RSS/RPS/RFS/XPS对比

    RSS适合于多队列网卡,把不同的流分散的不同的网卡多列中,至于网卡队列由哪个cpu处理还需要绑定网卡队列中断与cpu RPS:适合于单队列网卡或者虚拟网卡,把该网卡上的数据流让多个cpu处理 RFS: ...

  5. Quartz(任务调度)- job串行避免死锁

    参照:http://blog.csdn.net/haitaofeiyang/article/details/50737644 quartz框架中防止任务并行可以有两种方案:   1.如果是通过Meth ...

  6. @ResponseBody返回json时,json数据丢失或者报错

    现象: 1.报错:There is a cycle in the hierarchy! 2.返回至前台的json不完整,字段丢失. 错误原因: eg:entity1的属性有list<entiti ...

  7. TCP拥塞处理—Congestion Handing

      TCP拥塞处理-Congestion Handing 1 慢启动 2 拥塞避免 3 快重传/拥塞发生(拥塞发生时的快速重传) 4 快恢复

  8. Elasticsearch Java虚拟机配置详解(转)

    引言: 今天,事情终于发生了.Java6(Mustang),是2006年早些时候出来的,至今仍然应用在众多生产环境中,现在终于走到了尽头.已经没有什么理由阻止迁移到Java7(Dolphin)上了. ...

  9. LeetCode OJ 297. Serialize and Deserialize Binary Tree

    Serialization is the process of converting a data structure or object into a sequence of bits so tha ...

  10. Java is Pass-by-Value!

    Java is strictly pass-by-value. which means, when you pass a variable to a method, the method will j ...