盖世计划--0730--B班训练

A

哈哈,写过的题,看过的性质还能忘,这辈子有了。

一个性质,如果要将 A 序列通过相邻位置 +11 操作(总和不变,相当于传递)变为序列 B,设 sai=j=1iajsbi=j=1iaj

那么最少操作次数为:

i=1n|saisbi|

理解一下,从左到右考虑,首先 a1 要变成 b1,需要 |a1b1| 次操作,a2 变成 a2+a1b1a2 要变成 b2,需要 |a2+a1b1b2| 次操作,以此类推就是上式。

然后简单 DP,考场当然想到了,然后没有上面的东西不会转移,哈哈。设 fi,j,k 表示考虑了前 i 个位置,ai 变成了 j,前缀和为 k最小上式

这样转移要 O(m),感觉是 O(nm3) 的是吧。但是你发现枚举到 i 时,ai 的上限是 mi,不然前面的数就无法比它大了。所以 mimlogm

总复杂度为 O(nm2logm),有更好的 O(nm2),我不会。

B

可持久线段树维护哈希+二分加速比较字典序

我的题解

C

简单 DP + 根号分治

我的题解

D

期望题

我的题解

E

不会写了哥。

当时看了半天,发现自己平衡树就写了个模板题,能写个寄吧,然后鸽了。然后就考了。

等我训完平衡树凯旋归来,薄纱这道题!

OK,我会了。

每个时刻求出前 k 大,区间修改平衡树

具体过程:把前 k 大 split 出来,打延迟标记,同时看第 k 大是否为 0,如果是,说明不合法。

然后考虑怎么 merge 回去。你发现第 k 大的值不一定全都在前 k 大中,不能直接 merge,那就再把树 split 一下呗。把树分为四部分,就很容易 merge 了。

#include <bits/stdc++.h>
#define pii std::pair<int, int>
#define mk std::make_pair
#define fi first
#define se second
#define pb push_back

using i64 = long long;
using ull = unsigned long long;
const i64 iinf = 0x3f3f3f3f, linf = 0x3f3f3f3f3f3f3f3f;
const int N = 1e5 + 10;
int n, m, cnt, rt, x, y, z, l1, r1, l, r;
int a[N], b[N];
struct node {
	int pri, val, sz, l, r, tg;
} t[N];
int getnode(int a) {t[++cnt] = {rand(), a, 1, 0, 0, 0};return cnt;}
void pushup(int u) {
	t[u].sz = t[t[u].l].sz + t[t[u].r].sz + 1;
}
void pd(int u) {
	if(!t[u].tg) return;
	t[t[u].l].val += t[u].tg, t[t[u].l].tg += t[u].tg;
	t[t[u].r].val += t[u].tg, t[t[u].r].tg += t[u].tg;
	t[u].tg = 0;
}
void split(int u, int &x, int &y, int k) {
	if(!u) {x = y = 0; return;}
	pd(u);
	if(k <= t[t[u].l].sz) {
		y = u;
		split(t[u].l, x, t[u].l, k);
	} else {
		x = u;
		split(t[u].r, t[u].r, y, k - t[t[u].l].sz - 1);
	}
	pushup(u);
}
void splitv(int u, int &x, int &y, int v) {
	if(!u) {x = y = 0; return;}
	pd(u);
	if(t[u].val <= v) {
		x = u;
		splitv(t[u].r, t[u].r, y, v);
	} else {
		y = u;
		splitv(t[u].l, x, t[u].l, v);
	}
	pushup(u);
}
int merge(int u, int v) {
	if(!u || !v) return u ^ v;
	if(t[u].pri < t[v].pri) {
		pd(u);
		t[u].r = merge(t[u].r, v);
		pushup(u);
		return u;
	} else {
		pd(v);
		t[v].l = merge(u, t[v].l);
		pushup(v);
		return v;	
	}
}
void fake_main() {
	std::cin >> n >> m;

	int s = 0;
	for(int i = 1; i <= n; i++) std::cin >> a[i], s += a[i];

	for(int i = 1; i <= m; i++) std::cin >> b[i], s -= b[i];

	if(s) {
		std::cout << "NO\n";
		return;
	}
	std::sort(b + 1, b + m + 1);
	rt = cnt = 0;
	for(int i = 1; i <= m; i++) {
		rt = merge(rt, getnode(b[i]));
	}

	bool ok = 1;
	for(int i = 1; i <= n; i++) {
		split(rt, x, y, m - a[i]);
		z = y;
		while(t[z].l) pd(z), z = t[z].l;
		if(!t[z].val) {
			ok = 0;
			break;
		} 
		t[y].val--, t[y].tg--;
		if(!x) {
			rt = y;
			continue;
		}
		z = x;
		while(t[z].r) pd(z), z = t[z].r;
		int p = t[z].val;
		splitv(x, l1, r1, p - 1);
		splitv(y, l, r, p - 1);
		rt = merge(merge(l1, l), merge(r1, r));
	}

	std::cout << (ok ? "YES\n" : "NO\n");
}
int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    
	int T;
	std::cin >> T;
	while(T--) fake_main();

	return 0;
}

F

树形 DP + 背包

我的题解

总结

算是复习了之前的题,7 道写过 6 道就离谱。

posted @   Fire_Raku  阅读(13)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
more_horiz
keyboard_arrow_up dark_mode palette
选择主题
点击右上角即可分享
微信分享提示