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]]+ ...
随机推荐
- spark学习(2)--hadoop安装、配置
环境: 三台机器 ubuntu14.04 hadoop2.7.5 jdk-8u161-linux-x64.tar.gz (jdk1.8) 架构: machine101 :名称节点.数据节点.Secon ...
- SPOJ - HORRIBLE 【线段树】
思路 线段树 区间更新 模板题 注意数据范围 AC代码 #include <cstdio> #include <cstring> #include <ctype.h> ...
- 微服务架构~BFF和网关是如何演化出来的
介绍 BFF(Backend for Frontend)和网关Gateway是微服务架构中的两个重要概念,这两个概念相对比较新,有些开发人员甚至是架构师都不甚理解. 本文用假想的公司案例+图示的方式, ...
- Java底层代码实现单文件读取和写入(解决中文乱码问题)
需求: 将"E:/data/车站一次/阿坝藏族羌族自治州.csv"文件中的内容读取,写入到"E:/data//车站一次.csv". 代码: public cla ...
- 每天一个Linux命令(54)chkconfig命令
chkconfig命令检查.设置系统的各种服务. (1)用法: 用法: chkconfig [必要参数] [服务] (2)功能: 功能: chkconf ...
- LeetCode: Keyboard Row
代码长了些,但还是比较简单的 public class Solution { public String[] findWords(String[] words) { List<String> ...
- requests.post处理Content-Type: multipart/form-data的请求
前几天遇到一个需求,要调用一个接口发送请求,抓包之后得到的数据是这样的 上网看了一些资料得知,原来这个接口的数据是通过multipart/form-data格式传过去的,multipart/form- ...
- 发现一个小坑的地方,unity的协程,想要停止,必须以字符串启动
今天想要停止一个协成,发现调用 StopCoroutine(ShowDebug()); 竟然不管用,后来看了文档才知道,原来想要停止协成,必须用字符启动协程 StartCoroutine(" ...
- JZ2440专用dnw 支持xp、win7、win8和win10系统【转】
本文转载自:https://blog.csdn.net/czg13548930186/article/details/76999152 学习于韦东山百问网公司 本文用于解决win7以上系统使用dnw难 ...
- JSP语法及内置对象
JSP全名为Java Server Pages,中文名叫java服务器页面,其根本是一个简化的Servlet设计,它[1] 是由Sun Microsystems公司倡导.许多公司参与一起建立的一种动 ...