Rikka with sequence
Accepts: 34
Submissions: 144
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 65536/65536 K (Java/Others)
问题描述
众所周知,萌萌哒六花不擅长数学,所以勇太给了她一些数学问题做练习,其中有一道是这样的: 现在有一个序列,因为这个序列很任性,开始时空的。接下来发生了 n 个事件,每一个事件是以下两种之一: 1.勇太利用黑炎龙的力量在序列的开头、结尾以及每相邻两个元素之间都插入一个权值为 w 的元素。若第一步执行事件一,执行后数列仅有一个数字w. 2.勇太想要六花告诉他第 L 个元素到第 R 个中权值第 k 小的权值是多少。 当然,这个问题对于萌萌哒六花来说实在是太难了,你可以帮帮她吗?
输入描述
第一行一个正整数 n 。接下来 n 行每一行描述了一种操作: 1.如果输入格式是1 w,表示第一种事件。 2.如果输入格式是2 L R k,表示第二种事件。 1≤n≤105,1≤L≤R≤1018,1≤w≤109 ,保证 L,R,k 合法, R不会超过当前序列长度。
输出描述
对于每一个第二类事件,输出一个数字表示答案。
输入样例
6 1 3 1 1 2 2 3 2 1 2 2 3 5 2 2 1 4 4
输出样例
3 2 3
分析:1.对于给定的r,l,找出有哪些对应的元素及个数便可
2.找第k小用map就t了,改成排序就过了
总结:1.结合最近的校选比赛:对每一个数据范围进行仔细考虑,找到那些奇特范围的突破口
2.就像这道题,区间长度最大可达到2的几万次方之多,而这里只有l,r 只到1e18;
3.相对区间长度来说,区间包含的元素种类只有1e5,所以从元素种类下手就是一个很好的突破口
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
typedef long long LL;
typedef pair<int,LL>pii;
#define MAXN 100005
#define MAXM 65
int num[MAXN],n,cnt,op,total;
LL k,l,r;
pii ma[MAXM];
void find_kth()
{
sort(ma,ma + total);
for(int i = 0;i < total;i++)
{
k -= ma[i].second;
if(k <= 0)
{
printf("%d\n",ma[i].first);
return;
}
}
}
void solve()
{
l--;
total = 0;
for(int i = cnt;l != r;i--)
{
LL cur = (r - l + (r & 1)) >> 1;
if(cur)
{
ma[total].second = cur;
ma[total++].first = num[i];
}
r >>= 1;
l >>= 1;
}
find_kth();
}
int main()
{
while(scanf("%d",&n) != EOF)
{
cnt = 0;
for(int i = 0;i < n;i++)
{
scanf("%d",&op);
if(op == 1)scanf("%d",&num[++cnt]);
else
{
scanf("%I64d%I64d%I64d",&l,&r,&k);
solve();
}
}
}
}