题意:查询区间中位数

思路:模板题,相当于区间第K大的数,主席树可以水过,但划分树是正解。但还没搞明白划分树,先上模板

 #include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <string>
#include <vector>
#include <algorithm>
#include <set>
#define repu(i,a,b) for(int i=a;i<b;i++)
using namespace std;
#define N 1000010
#define ll long long
#define _cle(m, a) memset(m, a, sizeof(m))
const int MAXN = ;
const int M = MAXN * ;
int n,q,m,tot;
int a[MAXN], t[MAXN];
int T[MAXN], lson[M], rson[M], c[M];
void Init_Hash()
{
for(int i = ; i <= n; i++)
t[i] = a[i];
sort(t+,t++n);
m = unique(t+,t++n) -t-;
}
int build(int l, int r)
{
int root = tot++;
c[root] = ;
if(l != r)
{
int mid = (l+r)>>;
lson[root] = build(l,mid);
rson[root] = build(mid+,r);
}
return root;
}
int Hash(int x)
{
return lower_bound(t+,t++m,x) - t;
}
int update(int root, int pos, int val)
{
int newroot = tot++, tmp = newroot;
c[newroot] = c[root] + val;
int l = , r = m;
while(l < r)
{
int mid = (l+r)>>;
if(pos <= mid)
{
lson[newroot] = tot++;
rson[newroot] = rson[root];
newroot = lson[newroot];
root = lson[root];
r = mid;
}
else
{
rson[newroot] = tot++;
lson[newroot] = lson[root];
newroot = rson[newroot];
root = rson[root];
l = mid+;
}
c[newroot] = c[root] + val;
}
return tmp;
}
int query(int left_root, int right_root, int k)
{
int l = , r = m;
while( l < r)
{
int mid = (l+r)>>;
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 + ;
k -= c[lson[left_root]] - c[lson[right_root]];
left_root = rson[left_root];
right_root = rson[right_root];
}
}
return l;
}
int main()
{
//freopen("in.txt","r", stdin);
//freopen("out.txt","w", stdout);
int kase = ;
while(scanf("%d",&n) == )
{
tot = ;
for(int i = ; i <= n; i++)
scanf("%d",&a[i]);
Init_Hash();
T[n+] = build(,m);
for(int i = n; i ; i--)
{
int pos = Hash(a[i]);
T[i] = update(T[i+],pos,);
}
printf("Case %d:\n",kase++);
scanf("%d",&q);
while(q--)
{
int l,r,k;
scanf("%d%d",&l,&r);
k = (r-l)/+;
printf("%d\n",t[query(T[l],T[r+],k)]);
}
}
return ;
}

主席树

先上KB模板

 //划分树
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=;
int tree[][MAXN];//表示每层每个位置的值
int sorted[MAXN];//已经排序好的数
int toleft[][MAXN];//toleft[p][i]表示第i层从1到i有数分入左边
void build(int l,int r,int dep){
if(l==r)return;
int mid=(l+r)>>;
int same=mid-l+;//表示等于中间值而且被分入左边的个数
for(int i=l;i<=r;i++)//注意是l,不是one
if(tree[dep][i]<sorted[mid]) same--;
int lpos=l;
int rpos=mid+;
for(int i=l;i<=r;i++){
if(tree[dep][i]<sorted[mid]) tree[dep+][lpos++]=tree[dep][i];
else if(tree[dep][i]==sorted[mid]&&same>){
tree[dep+][lpos++]=tree[dep][i];
same--;
}
else tree[dep+][rpos++]=tree[dep][i];
toleft[dep][i]=toleft[dep][l-]+lpos-l;
}
build(l,mid,dep+);
build(mid+,r,dep+);
}
//查询区间第k大的数,[L,R]是大区间,[l,r]是要查询的小区间
int query(int L,int R,int l,int r,int dep,int k){
if(l==r)return tree[dep][l];
int mid=(L+R)>>;
int cnt=toleft[dep][r]-toleft[dep][l-];
if(cnt>=k){
int newl=L+toleft[dep][l-]-toleft[dep][L-];int newr=newl+cnt-;
return query(L,mid,newl,newr,dep+,k);
}
else{
int newr=r+toleft[dep][R]-toleft[dep][r],newl=newr-(r-l-cnt);
return query(mid+,R,newl,newr,dep+,k-cnt);
}
}
int main(){
int n,m,t=;
while(~scanf("%d",&n)){
memset(tree,,sizeof(tree));
for(int i=;i<=n;i++){
scanf("%d",&tree[][i]);
sorted[i]=tree[][i];
}
sort(sorted+,sorted+n+);
build(,n,);
scanf("%d",&m);
printf("Case %d:\n",++t);
int s,t,k;
while(m--){
scanf("%d%d",&s,&t);
k=(t-s+)/;
printf("%d\n",query(,n,s,t,,k));
}
}
return ;
}

划分树

HDU 4251 --- 主席树(划分树是正解)的更多相关文章

  1. 归并树 划分树 可持久化线段树(主席树) 入门题 hdu 2665

    如果题目给出1e5的数据范围,,以前只会用n*log(n)的方法去想 今天学了一下两三种n*n*log(n)的数据结构 他们就是大名鼎鼎的 归并树 划分树 主席树,,,, 首先来说两个问题,,区间第k ...

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

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

  3. HDU 2665 Kth number(划分树)

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

  4. HDU 3473 Minimum Sum 划分树,数据结构 难度:1

    http://acm.hdu.edu.cn/showproblem.php?pid=3473 划分树模板题目,需要注意的是划分树的k是由1开始的 划分树: 参考:http://blog.csdn.ne ...

  5. poj2104&&poj2761 (主席树&&划分树)主席树静态区间第k大模板

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

  6. POJ 题目2761 Feed the dogs(主席树||划分树)

    Feed the dogs Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 16860   Accepted: 5273 De ...

  7. HDU 4417 - Super Mario ( 划分树+二分 / 树状数组+离线处理+离散化)

    题意:给一个数组,每次询问输出在区间[L,R]之间小于H的数字的个数. 此题可以使用划分树在线解决. 划分树可以快速查询区间第K小个数字.逆向思考,判断小于H的最大的一个数字是区间第几小数,即是答案. ...

  8. hdu 2665 Kth number_划分树

    题意:求区间[a,b]的第k大 因为多次询问要用到划分树 #include <iostream> #include<cstdio> #include<algorithm& ...

  9. HDU 4417 Super Mario(划分树)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

随机推荐

  1. Linux 各文件夹介绍

    http://www.cnblogs.com/amboyna/archive/2008/02/16/1070474.html linux下的文件结构,看看每个文件夹都是干吗用的/bin 二进制可执行命 ...

  2. [问题2014A06] 解答

    [问题2014A06]  解答 用反证法, 设存在 \(n\) 阶正交阵 \(A,B\), 使得 \[A^2=cAB+B^2,\,\,c\neq 0.\cdots(1)\] 在 (1) 式两边同时左乘 ...

  3. eclipse https git

    open preferences via application menu Window => Preferences (or on OSX Eclipse => Settings). N ...

  4. C# 使用lock关键字lock不同的对象

    c# lock关键字的本质 是调用Monitor.Enter(object obj)并且在finally的时候调用Monitor.Exit(obj) 在obj是不同数据类型的时候会出现不同的情况 1. ...

  5. Excle隐藏及展开列

    当excle文档类目比较多的时候我们希望看第一列和某一列的对应关系可以选择隐藏中间列. 选中要隐藏的列,然后右键-->隐藏即可 需要展开的时候,选中:被隐藏列的前一列和后一列,然后当鼠标在列头( ...

  6. 程序设计入门——C语言 第1周编程练习 1逆序的三位数(5分)

    第1周编程练习 查看帮助 返回   第1周编程练习题,直到课程结束之前随时可以来做.在自己的IDE或编辑器中完成作业后,将源代码的全部内容拷贝.粘贴到题目的代码区,就可以提交,然后可以查看在线编译和运 ...

  7. 用spring的InitializingBean作初始化

    org.springframework.beans.factory包下有一个接口是InitializingBean 只有一个方法: /**  * Invoked by a BeanFactory af ...

  8. JQuery基础核心

    一.代码风格 在jQuery程序中,不管是页面元素的选择.内置的功能函数,都是美元符号“$”来起始的. 而这个“$”就是jQuery当中最重要且独有的对象:jQuery对象,所以我们在页面元素选择或执 ...

  9. Eclipse 最全快捷键

    英文的

  10. mybatis 模糊查询 like

    1.  参数中直接加入%% param.setUsername("%CD%");      param.setPassword("%11%"); <sel ...