专栏文章

P3730 曼哈顿交易 题解

P3730题解参与者 3已保存评论 2

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
2 条
当前快照
1 份
快照标识符
@miploroz
此快照首次捕获于
2025/12/03 14:02
3 个月前
此快照最后确认于
2025/12/03 14:02
3 个月前
查看原文
补充一种其他题解很少提到的做法。

题目分析

cnticnt_i 为持有 ii 股票的人数,本题要在区间内查询 cnticnt_i 的第 kk 小,这个信息很难直接用线段树等其他数据结构维护,于是考虑莫队。
我们将 cnticnt_i 再放入一个桶中,记 cnt2jcnt2_jcnti=jcnt_i=j 的个数,想要在这个桶中找到第 kk 小的,自然而然就可以想到对这个桶求前缀和,然后就可以通过二分快速地找到第 kk 小的数了。
接下来我们考虑莫队在区间扩展中对这个前缀和数组的影响。首先考虑向区间内加入一个数,设这个数为 vv,则 cntvcnt_v 会加一,对应到 cnt2cnt2 上就是 cnt2cntv1,cnt2cntv+1+1cnt2_{cnt_v}-1,cnt2_{cnt_v+1}+1,再看前缀和数组,cntvcnt_v 之后的位置 1-1+1+1 都会抵消掉,所以只需在 cntvcnt_v 的位置上减一。从区间中去除一个数也是同理。
总的时间复杂度为 O(nn+mlogn)O(n\sqrt n+m\log n)

AC代码

CPP
#include<bits/stdc++.h>
#define FOR(i, l, r) for(int (i)=(l); (i)<=(r); (i)++)
#define ROF(i, r, l) for(int (i)=(r); (i)>=(l); (i)--)
#define deb(x) cerr << "debug " << #x << ": " << x << endl;
using namespace std;
inline int read(){
	int x = 0, f = 1;
	char c = getchar();
	while(c>'9' || c<'0'){
		if(c=='-')f=-1;
		c=getchar();
	}
	while(c>='0' && c<='9'){
		x = (x<<1)+(x<<3)+c-48;
		c = getchar();
	}
	return x*f;
}
inline void write(int x){
	if(x<0){
		putchar('-');
		x = -x;
	}
	if(x>=10) write(x/10);
	putchar(x%10+48);
}
const int N = 1e5+10;
int cnt[N], sum[N], a[N], ls[N], ans[N];
struct ask{
	int l, r, k, id;
}q[N]; 
inline void add(int v){
	sum[cnt[v]++]--;
}
inline void del(int v){
	sum[--cnt[v]]++;
}
int main(){
	int n = read(),m = read(); 
	FOR(i,1,n)ls[i] = a[i] = read();
	sort(ls+1, ls+n+1);
	FOR(i,1,n)a[i] = lower_bound(ls+1, ls+n+1, a[i])-ls;
	FOR(i,1,m){
		q[i].id = i;
		q[i].l=read(),q[i].r=read(),q[i].k=read();
	}
	int t = sqrt(n);
	sort(q+1, q+m+1, [&](ask a, ask b){
		return a.l/t!=b.l/t?a.l/t<b.l/t:a.r<b.r;
	});
	int l = 0, r = 0;
	FOR(i,1,m){
		while(r>q[i].r)del(a[r--]);
		while(r<q[i].r)add(a[++r]);
		while(l<q[i].l)del(a[l++]);
		while(l>q[i].l)add(a[--l]);
		if(sum[n]-sum[0]<q[i].k)ans[q[i].id]=-1;
		else ans[q[i].id] = lower_bound(sum+1, sum+n+1, sum[0]+q[i].k)-sum; 
	} 
	FOR(i,1,m){
		printf("%d\n", ans[i]);
	}
	return 0;
}

评论

2 条评论,欢迎与作者交流。

正在加载评论...