HDU3727 Jewel(主席树+树状数组(或二分))
Problem Description
Initially, there is no bead at all, that is, there is an empty chain. Jimmy always sticks the new bead to the right of the chain, to make the chain longer and longer. We number the leftmost bead as Position 1, and the bead to its right as Position 2, and so on. Jimmy usually asks questions about the beads' positions, size ranks and actual sizes. Specifically speaking, there are 4 kinds of operations you should process:
Insert x
Put a bead with size x to the right of the chain (0 < x < 231, and x is different from all the sizes of beads currently in the chain)
Query_1 s t k
Query the k-th smallest bead between position s and t, inclusive. You can assume 1 <= s <= t <= L, (L is the length of the current chain), and 1 <= k <= min (100, t-s+1)
Query_2 x
Query the rank of the bead with size x, if we sort all the current beads by ascent order of sizes. The result should between 1 and L (L is the length of the current chain)
Query_3 k
Query the size of the k-th smallest bead currently (1 <= k <= L, L is the length of the current chain)
Input
You can assume the amount of "Insert" operation is no more than 100000, and the amounts of "Query_1", "Query_2" and "Query_3" are all less than 35000.
There are several test cases in the input. The first line for each test case is an integer N, indicating the number of operations. Then N lines follow, each line contains one operation, as described above.
You can assume the amount of "Insert" operation is no more than 100000, and the amounts of "Query_1", "Query_2" and "Query_3" are all less than 35000.Query the rank of the bead with size x, if we sort all the current beads by ascent order of sizes. The result should between 1 and L (L is the length of the current chain)
Query_3 k
Query the size of the k-th smallest bead currently (1 <= k <= L, L is the length of the current chain)
Output
Sample Input
Sample Output
Hint
The answers for the 5 queries are 6, 4, 3, 4, 1, respectively.
题意:
输入n,再输入n个操作,操作有四种
0, Insert X:插入x到序列末尾
1, query_1 L R X:在当前序列中的[l,r]区间找第x小的数。
2, query_2 X:在当前序列中,输出X是第几小的数。
3, query_3 X:找到当前序列中第X小的数是几。
然后输出的是3种query的和。
思路:
操作1和操作3是查询区间第k小,主席树。
操作2是求排名,用树状数组或者二分。
在线转化为离线。
求Kth的主席树的模板见我之前写的:http://www.cnblogs.com/hua-dong/p/7931778.html
操作2为二分的代码:
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int maxn=;
int a[maxn],b[maxn],Innum,n;//a是位置,b是值。Innum是输入的个数,即
int cnt,ql,qr,Case=;
long long sum1,sum2,sum3;
struct questions
{
int opt;//0,1,2,3
int x,y,k;
}Qst[maxn<<];
struct PLTree
{
int ch[maxn * ][],sum[maxn * ],rt[maxn];
void build(int& now,int l,int r)
{
now = ++ cnt;
sum[now] = ;
if(l == r) return ;
int Mid = (l + r)>>;
build(ch[now][],l,Mid);
build(ch[now][],Mid + ,r);
}
void insert(int& now,int last,int l,int r,int pos)
{
now = ++ cnt;
ch[now][]=ch[last][];
ch[now][]=ch[last][];
sum[now] = sum[last] + ;
if(l == r) return ;
int Mid = (l+r) >> ;
if(pos <= Mid) insert(ch[now][],ch[last][],l,Mid,pos);
else insert(ch[now][],ch[last][],Mid + ,r,pos);
}
int query(int ss,int tt,int l,int r,int k)
{
if(l == r) return l;
int Mid =(l + r) >> ,tmp = sum[ch[tt][]] - sum[ch[ss][]];
if(k <= tmp) return query(ch[ss][],ch[tt][],l,Mid,k);
else return query(ch[ss][],ch[tt][],Mid + ,r,k - tmp);
}
};
PLTree P;
void _init()
{
Innum=cnt=;
sum1=sum2=sum3=;
}
void _scanf()
{
char chr[];
for(int i=;i<=n;i++){
scanf("%s",chr);
if(chr[]=='I'){
Qst[i].opt=;
scanf("%d",&Qst[i].x);
a[++Innum]=Qst[i].x;
b[Innum]=a[Innum];
}
else {
Qst[i].opt=chr[]-'';
if(chr[]=='') scanf("%d%d%d",&Qst[i].x,&Qst[i].y,&Qst[i].k);
else scanf("%d",&Qst[i].k);
}
}
}
void _disp()
{
sort(b+,b+Innum+);
for(int i=;i<=Innum;i++)
a[i]=lower_bound(b+,b+Innum+,a[i])-b;
}
void _work()
{
P.build(P.rt[],,Innum);
int nowcnt=,ans;
for(int i=;i<=n;i++){
if(Qst[i].opt==) {
nowcnt++;
P.insert(P.rt[nowcnt],P.rt[nowcnt-],,Innum,a[nowcnt]);
}
else if(Qst[i].opt==){
ans=P.query(P.rt[Qst[i].x-],P.rt[Qst[i].y],,Innum,Qst[i].k);
sum1+=b[ans];
}
else if(Qst[i].opt==){
int L=,R=nowcnt;
while(L<=R){
int Mid=(L+R)>>;
ans=P.query(P.rt[],P.rt[nowcnt],,Innum,Mid);
if(b[ans]==Qst[i].k) {
sum2+=Mid;
break;
}
else if(b[ans]<Qst[i].k) L=Mid+;
else R=Mid-;
}
}
else {
ans=P.query(P.rt[],P.rt[nowcnt],,Innum,Qst[i].k);
sum3+=b[ans];
}
}
printf("Case %d:\n",++Case);
printf("%lld\n%lld\n%lld\n",sum1,sum2,sum3);
}
int main()
{
while(~scanf("%d",&n)){
_init();
_scanf();//输入
_disp();//离散
_work();
}
return ;
}
操作2为树状数组的代码:
#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<map>
using namespace std;
const int maxn=;
int a[maxn],b[maxn],Innum,n;//a是位置,b是值。Innum是操作为输入的个数,即
int cnt,ql,qr,Case=;
long long sum1,sum2,sum3;
int c[maxn<<];
int lowbit(int x )
{
return x&-x;
}
void add( int x )
{
while(x < Innum){
c[x]++;
x += lowbit ( x );
}
}
int sum(int x )
{
int ret = ;
while (x){
ret += c[x];
x -= lowbit ( x );
}
return ret;
}
struct questions
{
int opt;//0,1,2,3
int x,y,k;
}Qst[maxn<<];
struct PLTree
{
int ch[maxn * ][],sum[maxn * ],rt[maxn];
void build(int& now,int l,int r)
{
now = ++ cnt;
sum[now] = ;
if(l == r) return ;
int Mid = (l + r)>>;
build(ch[now][],l,Mid);
build(ch[now][],Mid + ,r);
}
void insert(int& now,int last,int l,int r,int pos)
{
now = ++ cnt;
ch[now][]=ch[last][];
ch[now][]=ch[last][];
sum[now] = sum[last] + ;
if(l == r) return ;
int Mid = (l+r) >> ;
if(pos <= Mid) insert(ch[now][],ch[last][],l,Mid,pos);
else insert(ch[now][],ch[last][],Mid + ,r,pos);
}
int query(int ss,int tt,int l,int r,int k)
{
if(l == r) return l;
int Mid =(l + r) >> ,tmp = sum[ch[tt][]] - sum[ch[ss][]];
if(k <= tmp) return query(ch[ss][],ch[tt][],l,Mid,k);
else return query(ch[ss][],ch[tt][],Mid + ,r,k - tmp);
}
};
PLTree P;
void _init()
{
Innum=cnt=;
sum1=sum2=sum3=;
memset(c,,sizeof(c));
}
void _scanf()
{
char chr[];
for(int i=;i<=n;i++){
scanf("%s",chr);
if(chr[]=='I'){
Qst[i].opt=;
scanf("%d",&Qst[i].x);
a[++Innum]=Qst[i].x;
b[Innum]=a[Innum];
}
else {
Qst[i].opt=chr[]-'';
if(chr[]=='') scanf("%d%d%d",&Qst[i].x,&Qst[i].y,&Qst[i].k);
else scanf("%d",&Qst[i].k);
}
}
}
void _disp()
{
sort(b+,b+Innum+);
for(int i=;i<=Innum;i++)
a[i]=lower_bound(b+,b+Innum+,a[i])-b;
}
void _work()
{
P.build(P.rt[],,Innum);
int nowcnt=,ans;
for(int i=;i<=n;i++){
if(Qst[i].opt==) {
nowcnt++;
P.insert(P.rt[nowcnt],P.rt[nowcnt-],,Innum,a[nowcnt]);
add(a[nowcnt]);
}
else if(Qst[i].opt==){
ans=P.query(P.rt[Qst[i].x-],P.rt[Qst[i].y],,Innum,Qst[i].k);
sum1+=b[ans];
}
else if(Qst[i].opt==){
int tmp=sum(lower_bound(b+,b+Innum+,Qst[i].k)-b);
sum2+=tmp;
}
else {
ans=P.query(P.rt[],P.rt[nowcnt],,Innum,Qst[i].k);
sum3+=b[ans];
}
}
printf("Case %d:\n",++Case);
printf("%lld\n%lld\n%lld\n",sum1,sum2,sum3);
}
int main()
{
while(~scanf("%d",&n)){
_init();
_scanf();//输入
_disp();//离散
_work();
}
return ;
}
HDU3727 Jewel(主席树+树状数组(或二分))的更多相关文章
- 【bzoj4889】[Tjoi2017]不勤劳的图书管理员 树状数组+分块+二分
题目描述(转自洛谷) 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度.现在有n本被打 ...
- [POJ2182]Lost Cows(树状数组,二分)
题目链接:http://poj.org/problem?id=2182 题意:给定1~n个数和n个位置,已知ai表示第i个位置前有ai个数比当前位置的数小,求这个排列. 和刚才YY的题意蛮接近的,用树 ...
- BZOJ 2738 子矩阵第k大 | 二维树状数组 整体二分 分治
BZOJ 2738 "矩阵乘法"(子矩阵第k大) 题意 给出一个矩阵,多次询问子矩阵中第k大的数是多少. 题解 我做这道题之前先照着这道题出了一道题,是这道题的一维版本,在这里:h ...
- 洛谷1527(bzoj2738)矩阵乘法——二维树状数组+整体二分
题目:https://www.luogu.org/problemnew/show/P1527 不难想到(?)可以用二维树状数组.但维护什么?怎么查询是难点. 因为求第k小,可以考虑记权值树状数组,把比 ...
- POJ2828 Buy Tickets [树状数组,二分答案]
题目传送门 Buy Tickets Time Limit: 4000MS Memory Limit: 65536K Total Submissions: 22611 Accepted: 110 ...
- 【洛谷3527】[POI2011] MET-Meteors(树状数组+整体二分)
点此看题面 大致题意: 一颗星球被分为\(M\)份,分别属于\(N\)个国家,有\(K\)场陨石雨,第\(i\)个国家希望收集\(P_i\)颗陨石,问其至少要在第几次陨石雨后才能达到目标. 关于整体二 ...
- 洛谷P1527 矩阵乘法——二维树状数组+整体二分
题目:https://www.luogu.org/problemnew/show/P1527 整体二分,先把所有询问都存下来: 然后二分一个值,小于它的加到二维树状数组的前缀和里,判断一遍所有询问,就 ...
- BZOJ3110[Zjoi2013]K大数查询(树状数组+整体二分)
3110 [Zjoi2013]K大数查询 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a ...
- 2019牛客暑期多校训练营(第七场)E-Find the median(思维+树状数组+离散化+二分)
>传送门< 题意:给n个操作,每次和 (1e9范围内)即往数组里面插所有 的所有数,求每次操作后的中位数思路:区间离散化然后二分答案,因为小于中位数的数字恰好有个,这显然具有单调性.那么问 ...
- Educational Codeforces Round 87 (Rated for Div. 2) D树状数组加二分删除的值
Sample Input 5 4 1 2 3 4 5 -5 -1 -3 -1 Sample Output 3 思路,首先发现a[i]的值的范围是在1~n之间,每次插入我们可以直接把cnt[a[i]]+ ...
随机推荐
- iOS 11 Xcode9开发 新特性学习 (警告篇)
最新版本SDK优化了开发体验,编译过程会提供更多提示警告,建议你修改.这些功能也可以自主选择用或者不用,当然,苹果喜欢你用他推荐的东西... 1 . @avalibale 语法,同步判断当前iOS系统 ...
- 大道至简(第五i章)读后感
大道至简(第五章)读后感 再一次在不想看的情况下读大道至简第五章,一个项目的实现中,“过程”与“工程”是同一个概念吗?答案自然是否定的.“过程”是一个确定的模板,而“工程”是有一个目的的实现在里面. ...
- 每天一个Linux命令(53)service命令
service命令用于对系统服务进行管理. (1)用法: 用法: service [服务] [操作] (2)功能: 功能: service命令用于启动.停止.重 ...
- Linux用户和用户组管理 用户组管理命令
添加用户组命令:groupadd 命令格式: [root@localhost ~]# groupadd [选项] 组名 选项: 选项 选项说明 -g GID 指定组ID: 修改用户组命令:groupm ...
- 0802 DRF 视图
昨日回顾: 1. Serializer(序列化) 1. ORM对应的query_set和ORM对象转换成JSON格式的数据 1. 在序列化类中定义自定义的字段:SerializerMethodFiel ...
- Nagios 服务安装
Nagios 环境部署 安装服务包 操作系统:Linux Centos 6.4 32位 安装包:nagios-3.4.3.tar.gz 安装包:nagios-plugins-1.4.13.tar.gz ...
- Qt编译器
有两种,MSVC和MINGW Qt 中有两种方式编译,一种是MinGW ,另一种MSVC. MSVC是指微软的VC编译器: MingGW是指是Minimalist GNU on Windows的缩写. ...
- INSPIRED启示录 读书笔记 - 第9章 产品副经理
发现帮手 从本质上讲,产品就是创意,产品经理的职责是想出好点并加以实现.我们需要好点子,有些想法是我们自己的创意,但如果仅依靠自己,就会严重限制创意的发挥 做产品要找公司最聪明的人合作,发现公司里潜在 ...
- c++ boost库学习三:实用工具
noncopyable 大家都知道定义一个空类的时候,它实际包含了构造函数,拷贝构造函数,赋值操作符和析构函数等. 这样就很容易产生一个问题,就是当用户调用A a(“^_^") 或者A c= ...
- CentOS 7 导入epel库
yum install epel-release 或者到百度云下载相应的 rpm 包进行安装 rpm -ivh epel-release-7-9.noarch.rpm