CSP-S开小灶3

A. 世界冰球锦标赛

原题

code

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
inline ull read(){
	ull x = 0; char c = getchar();
	while(c < '0' || c > '9')c = getchar();
	do{x = (x << 1) + (x << 3) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
	return x;
}
ull f[1050000], g[1050000], m, v[45], lg[1050000];
int n, n1, n2, c1, c2;
int main(){
	n = read(), m = read();
	n1 = n >> 1, n2 = n - n1;
	for(int i = 1; i <= max(n1, n2); ++i)lg[1 << i] = i;
	for(int i = 1; i <= n1; ++i)v[i] = read();
	c1 = 1 << n1;
	for(int i = 1; i < c1; ++i)f[i] = f[i xor (i & -i)] + v[lg[i & -i] + 1];
	for(int i = 1; i <= n2; ++i)v[i] = read();
	c2 = 1 << n2;
	for(int i = 1; i < c2; ++i)g[i] = g[i xor (i & -i)] + v[lg[i & - i] + 1];
	sort(f + 1, f + c1); sort(g + 1, g + c2);
	ull ans = 0; int p2 = 0;
	for(int i = c1 - 1; i >= 0; --i){
		while(p2 < c2 && g[p2] + f[i] <= m)++p2;
		ans += p2;
	}
	printf("%llu",ans);
	return 0;
}

B. 滚

考场认为自己打了个暴力,结果是复杂度分析错了?

用莫队维护当前的 \(f_x\)

然后维护一下 \(cnt_{f_x}\)

(我的代码里这两个是反过来的)

每次询问扫 \(cnt\) 即可

为啥是对的 ?

因为每次处理了\(f_x\)相同的, 然后\(\sum f_x\)为区间长度(最大为 \(n\)) 也就是说,存在值不同的 \(f_x\) 最多 \(\sqrt n\)

找有值的 \(cnt\) 的过程我是爆扫,如果构造一下数据是过不了的, 因为复杂度不对

正解应该爆扫 \(<= \sqrt n\) 的,对大于的用桶排序维护一下

有不少人用 \(set\) 那个会在莫队移动上乘个 \(log\) 复杂度也不对

或者像 \(Lyin\) 大佬一样打个链表?

懒得打了, 反正 \(TLEcodes\) 都过了

勉强算是\(AK\)一次???????????

code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int maxn = 200005;
inline int read(){
	int x = 0; char c = getchar();
	while(c < '0' || c > '9')c = getchar();
	do{x = (x << 1) + (x << 3) + (c ^ 48); c = getchar();}while(c <= '9' && c >= '0');
	return x;
}
int a[maxn], w[maxn], n, m, bl[maxn], len, ans[maxn];
struct Q{
	int l, r, k, id;
	friend bool operator < (const Q &x, const Q &y){
		return bl[x.l] == bl[y.l] ? x.r < y.r : x.l < y.l;
	}
}q[maxn];
int cnt[maxn], f[maxn];
int query(int k, int sum){
	int las = -0x3f3f3f3f, mx = -1;
	for(int i = 1; sum; ++i)if(f[i]){
		sum -= f[i] * i; if(las + k >= i)mx = max(mx, w[i]);
		las = i;
	}
	return mx;
}
void add(int col){
	if(cnt[col] > 0)--f[cnt[col]];
	++f[++cnt[col]];
}
void del(int col){
	--f[cnt[col]--];
	if(cnt[col] > 0)++f[cnt[col]];
}
void solve(){
	int l = 0, r = 0;
	for(int i = 1; i <= m; ++i){
		while(q[i].l < l)add(a[l - 1]), --l;
		while(q[i].r > r)add(a[r + 1]), ++r;
		while(q[i].l > l)del(a[l]), ++l;
		while(q[i].r < r)del(a[r]), --r;
		ans[q[i].id] = query(q[i].k, q[i].r - q[i].l + 1);
	}
}
int main(){
	n = read(), m = read();
	for(int i = 1; i <= n; ++i)a[i] = read();
	for(int i = 1; i <= n; ++i)w[i] = read();
	for(int i = 1; i <= m; ++i)q[i].id = i, q[i].l = read(), q[i].r = read(), q[i].k = read();
	len = sqrt(n);
	for(int i = 1; i <= n; ++i)bl[i] = (i + len - 1) / len;
	sort(q + 1, q + m + 1);
	solve();
	for(int i = 1; i <= m; ++i)printf("%d\n",ans[i]);
	return 0;
}
posted @ 2022-09-12 21:34  Chen_jr  阅读(41)  评论(3编辑  收藏  举报