链接:http://acm.hdu.edu.cn/showproblem.php?pid=5204
Rikka with sequence
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 757 Accepted Submission(s): 136
Problem Description
As we know, Rikka is poor at math. Yuta is worrying about this situation, so he gives Rikka some math tasks to practice. There is one of them:
Yuta have a sequence. Because the sequence is very self-willed(RenXing), at first the sequence is empty. And then Yuta do n operations on this sequence, each operation is either of these two types:
1.Add a number w into each gap of the sequence. For example if w=3 and the sequence before is “2 4”, it will be changed to “3 2 3 4 3”.
**after the first operation of the first type, there is only one number in the sequence**
2.Query the kth small number in the subsequence [L,R]. For example if k=2, L=2, R=4 and the sequence is “3 2 3 4 2”, the answer will be 3.
Yuta wants Rikka to tell him the answer of each query.
It is too difficult for Rikka. Can you help her?
Yuta have a sequence. Because the sequence is very self-willed(RenXing), at first the sequence is empty. And then Yuta do n operations on this sequence, each operation is either of these two types:
1.Add a number w into each gap of the sequence. For example if w=3 and the sequence before is “2 4”, it will be changed to “3 2 3 4 3”.
**after the first operation of the first type, there is only one number in the sequence**
2.Query the kth small number in the subsequence [L,R]. For example if k=2, L=2, R=4 and the sequence is “3 2 3 4 2”, the answer will be 3.
Yuta wants Rikka to tell him the answer of each query.
It is too difficult for Rikka. Can you help her?
Input
The first line contains one number
n(n≤100000)
. Each of the following
n
lines describes an operation: if it is “1 w” it will be the first type. Otherwise if it is “2 L R k”, it will be the second type.
(1≤w≤109,L≤R≤1018)
R will not be larger than the length of the sequence
R will not be larger than the length of the sequence
Output
For each query operation, output one number – the answer.
Sample Input
6 1 3 1 1 2 2 3 2 1 2 2 3 5 2 2 1 4 4
Sample Output
3 2 3
题意:
n个操作。
一开始一个空序列
op==1 给你一个数, 如果序列为空,就添加这个数。序列非空,就在集最前面加这个数,并在以后的所有数字后面加上这个数字。
op==2 询问区间第k大。
做法:
有一个规律。 对于1到L区间。前一个1操作产生的数 出现 (L+1)/2 次,然后再前一个出现 (L-(L+1)/2+1)/2次类推。
每次 都会 折半,所以最多出现60个数。
所以先把1到(L-1)区间 中 出现的数 -1, 然后把1到R 区间中出现的数 +1,然后排序下这60个数,数到第k个就可以了。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <malloc.h>
#include <ctype.h>
#include <math.h>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;
#include <stack>
#include <queue>
#include <vector>
#include <deque>
#include <set>
#include <map>
typedef __int64 ll;
ll op[100100];
ll num[100100];
ll bit[70];
void deal(ll wei,ll x)
{
ll ji=1;//前一个
while(wei)
{
bit[ji]+=x*(wei+1)/2;
wei-=(wei+1)/2;
ji++;
}
}
struct point
{
ll num,bit;
};
point tnum[70];
ll cmp(point a,point b)
{
return a.num<b.num;
}
int main()
{
ll n;
scanf("%I64d",&n);
ll len=1;
for(ll i=1;i<=n;i++)
{
scanf("%I64d",&op[i]);
if(op[i]&1)
{
scanf("%I64d",&num[len++]);
}
else
{
ll l,r,kk;
scanf("%I64d%I64d%I64d",&l,&r,&kk);
memset(bit,0,sizeof bit);
deal(r,1);
deal(l-1,-1);
for(ll i=1;i<=65;i++)//前一个 是 sum[len-i];
{
tnum[i].bit=bit[i];
tnum[i].num=num[len-i];
}
sort(tnum+1,tnum+1+65,cmp);
for(ll i=1;i<=65;i++)
{
kk-=tnum[i].bit;
if(kk<=0)
{
printf("%I64d\n",tnum[i].num);
break;
}
}
}
}
return 0;
}