Problem Description

Jimmy wants to make a special necklace for his girlfriend. He bought many beads with various sizes, and no two beads are with the same size. Jimmy can't remember all the details about the beads, for the necklace is so long. So he turns to you for help.

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

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.
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

Output 4 lines for each test case. The first line is "Case T:", where T is the id of the case. The next 3 lines indicate the sum of results for Query_1, Query_2 and Query_3, respectively.

 

Sample Input

10
Insert 1
Insert 4
Insert 2
Insert 5
Insert 6
Query_11 5 5
Query_1 2 3 2
Query_2 4
Query_3 3
Query_3 1
 

Sample Output

Case 1:
10
3
5

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(主席树+树状数组(或二分))的更多相关文章

  1. 【bzoj4889】[Tjoi2017]不勤劳的图书管理员 树状数组+分块+二分

    题目描述(转自洛谷) 加里敦大学有个帝国图书馆,小豆是图书馆阅览室的一个书籍管理员.他的任务是把书排成有序的,所以无序的书让他产生厌烦,两本乱序的书会让小豆产生这两本书页数的和的厌烦度.现在有n本被打 ...

  2. [POJ2182]Lost Cows(树状数组,二分)

    题目链接:http://poj.org/problem?id=2182 题意:给定1~n个数和n个位置,已知ai表示第i个位置前有ai个数比当前位置的数小,求这个排列. 和刚才YY的题意蛮接近的,用树 ...

  3. BZOJ 2738 子矩阵第k大 | 二维树状数组 整体二分 分治

    BZOJ 2738 "矩阵乘法"(子矩阵第k大) 题意 给出一个矩阵,多次询问子矩阵中第k大的数是多少. 题解 我做这道题之前先照着这道题出了一道题,是这道题的一维版本,在这里:h ...

  4. 洛谷1527(bzoj2738)矩阵乘法——二维树状数组+整体二分

    题目:https://www.luogu.org/problemnew/show/P1527 不难想到(?)可以用二维树状数组.但维护什么?怎么查询是难点. 因为求第k小,可以考虑记权值树状数组,把比 ...

  5. POJ2828 Buy Tickets [树状数组,二分答案]

    题目传送门 Buy Tickets Time Limit: 4000MS   Memory Limit: 65536K Total Submissions: 22611   Accepted: 110 ...

  6. 【洛谷3527】[POI2011] MET-Meteors(树状数组+整体二分)

    点此看题面 大致题意: 一颗星球被分为\(M\)份,分别属于\(N\)个国家,有\(K\)场陨石雨,第\(i\)个国家希望收集\(P_i\)颗陨石,问其至少要在第几次陨石雨后才能达到目标. 关于整体二 ...

  7. 洛谷P1527 矩阵乘法——二维树状数组+整体二分

    题目:https://www.luogu.org/problemnew/show/P1527 整体二分,先把所有询问都存下来: 然后二分一个值,小于它的加到二维树状数组的前缀和里,判断一遍所有询问,就 ...

  8. BZOJ3110[Zjoi2013]K大数查询(树状数组+整体二分)

    3110 [Zjoi2013]K大数查询 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c如果是2 a b c形式,表示询问从第a ...

  9. 2019牛客暑期多校训练营(第七场)E-Find the median(思维+树状数组+离散化+二分)

    >传送门< 题意:给n个操作,每次和 (1e9范围内)即往数组里面插所有 的所有数,求每次操作后的中位数思路:区间离散化然后二分答案,因为小于中位数的数字恰好有个,这显然具有单调性.那么问 ...

  10. 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]]+ ...

随机推荐

  1. Harbor私有仓库搭建

    1.安装docker yum install -y dockersystemctl start dockersystemctl enable docker 2.安装docker-compose 1.下 ...

  2. time函数计算时间

    学过C语言的都知道有个time函数可以计算时间, 也好像知道time(NULL)返回的是一个距离1970年1月1日0时0分0秒的秒数. #include <stdio.h> #includ ...

  3. $Java HttpClient库的使用

    (一)简介 HttpClient是Apache的一个开源库,相比于JDK自带的URLConnection等,使用起来更灵活方便. 使用方法可以大致分为如下八步曲: 1.创建一个HttpClient对象 ...

  4. sql中in和exists的区别效率问题 转

    in 和exists in是把外表和内表作hash 连接,而exists 是对外表作loop 循环,每次loop 循环再对内表进行查询. 一直以来认为exists 比in 效率高的说法是不准确的.如果 ...

  5. 如何在IAR中配置CRC参数(转)

    源:如何在IAR中配置CRC参数 前言 STM32全系列产品都具有CRC外设,对CRC的计算提供硬件支持,为应用程序节省了代码空间.CRC校验值可以用于数据传输中的数据正确性的验证,也可用于数据存储时 ...

  6. 主攻ASP.NET.4.5.1 MVC5.0之重生:创建UIHelper通用自定义分页和选择开关与PagesHelper和IsSelect简单用法

    @helper放入地方 分页效果 选择开关编辑调用 <dl> <dd class="dc1">是否主管:</dd> <dd> @UI ...

  7. 七、golang中接口、反射

    一.接口定义 1.定义 interface类型可以定义一组方法,但是这些不需要实现,并且interface不能包含任何变量 package main import ( "fmt" ...

  8. 在unity 中,使用http请求,下载文件到可读可写路径

    在这里我用了一个线程池,线程池参数接收一个带有object参数的,无返回值的委托 ,下载用到的核心代码,网上拷贝的,他的核心就是发起一个web请求,然后得到请求的响应,读取响应的流 剩下的都是常见的I ...

  9. 《机器学习实战第7章:利用AdaBoost元算法提高分类性能》

    import numpy as np import matplotlib.pyplot as plt def loadSimpData(): dataMat = np.matrix([[1., 2.1 ...

  10. create_workqueue和create_singlethread_workqueue【转】

    本文转载自:http://bgutech.blog.163.com/blog/static/18261124320116181119889/ 1. 什么是workqueueLinux中的Workque ...