poj2104&&poj2761 (主席树&&划分树)主席树静态区间第k大模板
Time Limit: 20000MS | Memory Limit: 65536K | |
Total Submissions: 43315 | Accepted: 14296 | |
Case Time Limit: 2000MS |
Description
That is, given an array a[1...n] of different integer numbers, your
program must answer a series of questions Q(i, j, k) in the form: "What
would be the k-th number in a[i...j] segment, if this segment was
sorted?"
For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the
question be Q(2, 5, 3). The segment a[2...5] is (5, 2, 6, 3). If we sort
this segment, we get (2, 3, 5, 6), the third number is 5, and therefore
the answer to the question is 5.
Input
first line of the input file contains n --- the size of the array, and m
--- the number of questions to answer (1 <= n <= 100 000, 1 <=
m <= 5 000).
The second line contains n different integer numbers not exceeding 109 by their absolute values --- the array for which the answers should be given.
The following m lines contain question descriptions, each
description consists of three numbers: i, j, and k (1 <= i <= j
<= n, 1 <= k <= j - i + 1) and represents the question Q(i, j,
k).
Output
Sample Input
7 3
1 5 2 6 3 7 4
2 5 3
4 4 1
1 7 3
Sample Output
5
6
3
Hint
Source
给定一个区间,求区间的第k大小的值
该题求的是静态区间第k大,是主席树的入门题目,但是划分树也可以轻松解决,下面两个代码都有
主席树代码
/* ***********************************************
Author :kuangbin
Created Time :2013-9-4 20:13:20
File Name :POJ2104.cpp
************************************************ */ #include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std; const int MAXN = ;
const int M = MAXN * ;
int n,q,m,tot;
int a[MAXN], t[MAXN];
int T[M], 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);
while(scanf("%d%d",&n,&q) == )
{
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,);
}
while(q--)
{
int l,r,k;
scanf("%d%d%d",&l,&r,&k);
printf("%d\n",t[query(T[l],T[r+],k)]);
}
}
return ;
}
划分树代码
#include<stdio.h>
#include<iostream>
#include<string.h>
#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++)
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;//从1到i放左边的个数 }
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-];//[l,r]中位于左边的个数
if(cnt>=k)
{
//L+要查询的区间前被放在左边的个数
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];
int newl=newr-(r-l-cnt);
return query(mid+,R,newl,newr,dep+,k-cnt);
}
} int main(){
int T;
int n,m;
int s,t,k;
int cnt=;
while(scanf("%d%d",&n,&m)!=EOF)
{
cnt++;
//scanf("%d%d",&n,&m);
memset(tree,,sizeof(tree));//这个必须
for(int i=;i<=n;i++)//从1开始
{
scanf("%d",&tree[][i]);
sorted[i]=tree[][i];
}
sort(sorted+,sorted+n+);
build(,n,); // printf("Case %d:\n",cnt);
while(m--)
{
scanf("%d%d%d",&s,&t,&k);
printf("%d\n",query(,n,s,t,,k));
}
}
return ;
}
poj2104&&poj2761 (主席树&&划分树)主席树静态区间第k大模板的更多相关文章
- 可持久化线段树(主席树)——静态区间第k大
主席树基本操作:静态区间第k大 #include<bits/stdc++.h> using namespace std; typedef long long LL; ,MAXN=2e5+, ...
- 主席树(静态区间第k大)
前言 如果要求一些数中的第k大值,怎么做? 可以先就这些数离散化,用线段树记录每个数字出现了多少次. ... 那么考虑用类似的方法来求静态区间第k大. 原理 假设现在要有一些数 我们可以对于每个数都建 ...
- 静态区间第k大(归并树)
POJ 2104为例 思想: 利用归并排序的思想: 建树过程和归并排序类似,每个数列都是子树序列的合并与排序. 查询过程,如果所查询区间完全包含在当前区间中,则直接返回当前区间内小于所求数的元素个数, ...
- POJ 2104 && POJ 2761 (静态区间第k大,主席树)
查询区间第K大,而且没有修改. 使用划分树是可以做的. 作为主席树的入门题,感觉太神奇了,Orz /* *********************************************** ...
- 静态区间第k大(主席树)
POJ 2104为例(主席树入门题) 思想: 可持久化线段树,也叫作函数式线段树,也叫主席树(高大上). 可持久化数据结构(Persistent data structure):利用函数式编程的思想使 ...
- HDU 2665 Kth number(主席树静态区间第K大)题解
题意:问你区间第k大是谁 思路:主席树就是可持久化线段树,他是由多个历史版本的权值线段树(不是普通线段树)组成的. 具体可以看q学姐的B站视频 代码: #include<cmath> #i ...
- 主席树初步学习笔记(可持久化数组?静态区间第k大?)
我接触 OI也快1年了,然而只写了3篇博客...(而且还是从DP跳到了主席树),不知道我这个机房吊车尾什么时候才能摸到大佬们的脚后跟orz... 前言:主席树这个东西,可以说是一种非常畸形的数据结构( ...
- 主席树学习笔记(静态区间第k大)
题目背景 这是个非常经典的主席树入门题——静态区间第K小 数据已经过加强,请使用主席树.同时请注意常数优化 题目描述 如题,给定N个整数构成的序列,将对于指定的闭区间查询其区间内的第K小值. 输入输出 ...
- POJ2104-- K-th Number(主席树静态区间第k大)
[转载]一篇还算可以的文章,关于可持久化线段树http://finaltheory.info/?p=249 无修改的区间第K大 我们先考虑简化的问题:我们要询问整个区间内的第K大.这样我们对值域建线段 ...
随机推荐
- IE下的圆角
元素{ position: relative;/*必须*/ z-index: 10;/*必须*/ border-radius: 8px; -moz-border-radius: 8px; -webki ...
- cacti添加被监控机全过程
在被监控端上的操作: 1.在被监控机器上root目录下建立文件 test.sh chmod 777 test.sh cat test #!/bin/bash echo $RANDOM 2.在snmpd ...
- 生鲜o2o配送应用系统,包括Android源码+SSH带后台管理系统
前台功能划分 我的 登录 账户+密码 注册 订单管理 查看/删除(显示订单详情) 支付(提交订单) ...
- ubuntu16 安装elasticsearch6.3问题
1.ubuntu16 安装elasticsearch6.3 elasticsearch 6.3需要的java的版本是1.8以上 安装java1.8 详见本博客的安装java https://www.c ...
- aspose.cell 给excel表格设置样式
方法1: Style styleTitle = workbook.Styles[workbook.Styles.Add()];//新增样式 styleTitle.HorizontalAlignment ...
- UVA - 1279 Asteroid Rangers (动点的最小生成树)
题意,有n个匀速动点,求最小生成树的改变次数. 一句话总结:动态问题的一般做法是先求出一个静态的解,然后求出解发生改变的事件,事件按照时间排序,依次处理. 先求出最开始的最小生成树(MST),当MST ...
- 强化学习_PolicyGradient(策略梯度)_代码解析
使用策略梯度解决离散action space问题. 一.导入包,定义hyper parameter import gym import tensorflow as tf import numpy as ...
- QR 分解
将学习到什么 介绍了平面旋转矩阵,Householder 矩阵和 QR 分解以入相关性质. 预备知识 平面旋转与 Householder 矩阵是特殊的酉矩阵,它们在建立某些基本的矩阵分解过程中起着 ...
- websocket 入门
什么是websocket WebSocket是HTML5新增的协议,它的目的是在浏览器和服务器之间建立一个不受限的双向通信的通道,比如说,服务器可以在任意时刻发送消息给浏览器. 为什么会出现 webs ...
- Ckeditor for Drupal
Ckeditor for Drupal 关于Drupal的所见即所得编辑器,Ckeditor是一个不错的选择,而且可以在Ckeditor官网直接下载到专为Drupal制作的版本: http:/ ...