hdu 5204 Rikka with sequence yy题

链接: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?
 

Input
The first line contains one number  n(n100000) . 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.  (1w109,LR1018)
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;
}
 










  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值