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]]+ ...
随机推荐
- Centos7.2安装bacula及bacula-web
serverd端安装(centos7) bacula的安装很简单,但是配置文件内容很多,配置不正确服务就启动不了,所以需要用webmin来配置. 1.安装基础软件包: 关闭SElinux(重要)set ...
- yii 2 局部关闭 CSRF 拦截
最近在拿 yii 2.0 开发ajax提交,在 post 请求接口时,提示数据无法验证,于是查询 yii 错误日志,发现错误为 exception ‘yiiwebBadRequestHttpExcep ...
- 每日练习level-7
1.有序列表.无序列表.自定义列表如何使用?写个简单的例子.三者在语义上有什么区别?使用场景是什么? 能否嵌套? 有序列表是一列使用数字进行标记的项目,它使用<li>包含于<ol&g ...
- linux 无密码登录
环境:Linux 脚本:Python 功能:批量IP,远程执行命令.拷贝文件 运行:./ssh_scp.py iplist.txt 脚本内容: #!/usr/bin/env python# -*- c ...
- INSPIRED启示录 读书笔记 - 第9章 产品副经理
发现帮手 从本质上讲,产品就是创意,产品经理的职责是想出好点并加以实现.我们需要好点子,有些想法是我们自己的创意,但如果仅依靠自己,就会严重限制创意的发挥 做产品要找公司最聪明的人合作,发现公司里潜在 ...
- Kubernetes pod网络解析
在Kubernetes中,会为每一个pod分配一个IP地址,pod内的所有容器都共享这个pod的network namespace,彼此之间使用localhost通信. 那么pod内所有容器间的网络是 ...
- 九度oj-题目1103:二次方程计算器
时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2799 解决:633 题目描述: 设计一个二次方程计算器 输入: 每个案例是关于x的一个二次方程表达式,为了简单,每个系数都是整数形式. 输 ...
- Spring中为什么实体类不用注入
要理解为什么不用注入,首先就清楚注入的目的是什么?如果不注入,在程序中要使用某个类对象的方法,则需要去new一个对象.然后我们调用其中的方法,众所周知"程序=算法+数据".不失一般 ...
- VC 模拟CMD 匿名管道
#include "stdafx.h" #include <Windows.h> #include <stdio.h> #include <stdli ...
- cos用在什么场景
随着应用的不断发展,应用过的图片,文件会不断增加, 存储量的提升带来的是IO用量的提升和带宽占用增加 大部分文件属于低频文件,但是占用较大 硬盘的变更需要重启机器 这个循环会造成支出不断增加 为了节省 ...