首页 > 其他分享 >01.03 CW 模拟赛 T4. ring

01.03 CW 模拟赛 T4. ring

时间:2025-01-04 09:22:01浏览次数:1  
标签:pre ch log int T4 01.03 mathcal CW size

前言

找原题未遂了()
\(\rm{HD0X}\) 大佬讲了没听懂啊

思路

无敌了, 看起来似乎很困难, 不知道补不补的掉

首先发现不好处理成一种简单的问题, 肯定是想有哪些方法可以处理这种问题
\(\rm{TJ}\) 的不太看得懂

  • 你可以树状数组维护区间和, 每次对于一个环暴力修改 \(\mathcal{O} (sz \log n)\), 然后查询 \(\mathcal{O} (\log n)\)
  • 你也可以对一个环标记其旋转次数, 这样子做修改是 \(\mathcal{O} (1)\) 的, 查询比较复杂:
    首先我们对于每个环计算其对区间的贡献, 具体的, 二分查找这个环的贡献区间, 然后常规计算
    那么这样子查询是 \(\mathcal{O} (m \log sz)\)

现在我们已经有了这两种做法, 你发现这两种做法完全不同阶, 第一种做法 \(sz\) 影响最大, 第二种做法 \(m\) 影响最大, 考虑根号分治
所以设阈值 \(B\) , 假设低于阈值使用方法 \(1\) , 否则使用方法 \(2\) , 因为 \(sz\) 足够大时, 方法 \(2\) 的查询复杂度将被压缩

你发现现在的总时间复杂度为 \(\mathcal{O} (B \log n + \frac{n}{B} \log n)\) (假设 \(n, m, q\) 同阶)

令 \(B = \sqrt{n}\) , 时间复杂度达到最优, 为 \(\mathcal{O} (n \sqrt{n \log^2 n})\)

这什么神经复杂度, 算了一下达到了 \(9 \times 10^8\) , 肯定是搞不过去的
啊, 过啦

考虑优化, 但是不用也能过, 参考 题解

实现

框架

写的清楚一点, 这是码力题 :
首先处理每一个环的大小 (根据阈值分开)
对于每次修改, 小环直接暴力旋转, 大环打个标记
对于每次查询, 小环直接树状数组启动, 对于大环单独计算贡献

代码

参考 \(\rm{KLR}\) 大佬的代码

#include "iostream"
#include "algorithm"

using namespace std;

#define int long long
#define lowbit(x) x & -x
//#define getchar getchar_unlocked

template <class T>
void read(T &x) {
	x = 0; char ch = getchar();
	while (ch < '0' or ch > '9') ch = getchar();
	while (ch >= '0' and ch <= '9') x = x * 10 + ch - 48, ch = getchar();
}

void print(int x) {
	if (x > 9) print(x / 10);
	putchar(x % 10 + '0');
}

constexpr int N = 1.5e5 + 10, B = 666;

int n, m, Q;
int a[N], tg[N];
basic_string<int> c[N], pre[N], ex;

class Binary_Indexed_Tree {
protected:
	int tr[N];
	
public:	
	void update(int x, int k) { for (; x <= n; x += lowbit(x)) tr[x] += k; }
	
	int query(int x) {
		int ret = 0;
		for (; x; x -= lowbit(x)) ret += tr[x];
		return ret;	
	}
	
	int query(int l, int r) { return query(r) - query(l - 1); }
	
} bit;

void init() {
	read(n), read(m), read(Q);
	for (int i = 1, x; i <= n; ++i) read(x), c[x].push_back(i);
	for (int i = 1; i <= n; ++i) read(a[i]);
	for (int i = 1; i <= m; ++i) {
		if (c[i].size() <= B) for (int x : c[i]) bit.update(x, a[x]);
		else {
			ex.push_back(i);
			int tmp = 0;
			for (int x : c[i]) pre[i].push_back(tmp += a[x]);
		}
	}
}

int deal(int x, int l, int r) {
	l = lower_bound(c[x].begin(), c[x].end(), l) - c[x].begin(), r = upper_bound(c[x].begin(), c[x].end(), r) - c[x].begin() - 1;
	if (l >= (int)c[x].size() or r < l) return 0;
	l = (l + c[x].size() - tg[x]) % c[x].size(), r = (r + c[x].size() - tg[x]) % c[x].size();
	if (l > r) return *pre[x].rbegin() - (pre[x][l - 1] - pre[x][r]);
	return pre[x][r] - (l ? pre[x][l - 1] : 0);
}

void swp(int x) {
	if (c[x].empty()) return;
	for (int i : c[x]) bit.update(i, -a[i]);
	bit.update(c[x][0], a[c[x][c[x].size() - 1]]);
	for (int i = c[x].size() - 1; i; --i) bit.update(c[x][i], a[c[x][i - 1]]);
	for (int i = c[x].size() - 1; i; --i) swap(a[c[x][i]], a[c[x][i - 1]]);
}

void calculate() {
	while (Q--) {
		int op, l, r;
		read(op), read(l);
		if (op & 1) {
			read(r);
			int ans = bit.query(l, r);
			for (int x : ex) ans += deal(x, l, r);
			print(ans), putchar('\n');
		}
		else {
			if (c[l].size() <= B) swp(l);
			else ++tg[l];
		}
	}
}

void solve() {
	init();
	calculate();
}

signed main() {
	solve();
	return 0;
}

总结

这个题的 \(\rm{subtask}\) 提示的非常完备, 挨着想肯定能想出来

根号分治无敌, 这个题属于超级巨大根号分治, 害怕

多种做法可以用根号分治均摊, 前提是需要有可以分治的点

标签:pre,ch,log,int,T4,01.03,mathcal,CW,size
From: https://www.cnblogs.com/YzaCsp/p/18651449

相关文章

  • Diary - 2025.01.03
    今天简直是唐完了,糖糖。晚上想啥啥不会,看了题解还写不出来。我去我是不是没救了???今天的事没有办法,就鸽到明天去吧(。whk结束啦!!!看来pku还是挺良心的,有优异的还能直接打,太感动了!!!比较意外的是我居然去年pkusc也是优异,毕竟我觉得那场打的还是有点差的(。明天看起来是没有模......
  • 01.03 CW 模拟赛 T2. game
    思路先把赛时的思路搬一下你发现确定两个人的起始点,其实是可以确定\(\rm{Alice}\)的选点可能的,考虑写个代码验证一下具体的,就是分成两个弧,\(\rm{Alice}\)可以选择一个弧的优势(过半),然后其他的劣势感觉现在是猜结论,全靠感性,我也不知道怎么解释这个问题那么......
  • 25.01.03
    喜欢我\(O(n^2\log^2n)\)过\(2e5\)吗......
  • 01.03 CW 模拟赛 T1. math
    前言赛场上\(\rm{while}\)打成\(\rm{if}\)痛失\(40\rm{pts}\)不过下来看是贪心的话也没什么好做的了,一般都不会对了这是题目题目下载\(\rm{sol}\)方法\(1\):逐位计算思路显然的是你需要把数字从大到小填入,使得高位的数尽量大,这个显然由上面的结论可以知道......
  • 2025.01.03 LGJ Round
    A一个序列\(a\),你需要对其每个前缀计算:至少要多少次交换相邻元素的操作使得序列变为“单峰”,即由一个递增序列和一个递减序列拼起来。\(n\le5e5\)。我一开始的想法是:枚举切点,左边的数排序成递增,右边的数排序为递减,贡献是逆序对+正序对。然而这是错误,因为不保证左边的某个数去......
  • 1.3 CW 模拟赛 赛时记录
    前言还是传统手法,冲冲冲看题\(\rm{T1}\)好吧,不会高精度,寄了\(\rm{T2}\)博弈\(\rm{T3}\)我不到啊\(\rm{T4}\)看不懂思密达首先这套题肯定不是能拿大分的题,所以今天尽量多分析,给每个题留足思考时间,然后多打暴力,最后拼高分/正解以后也尽量做到看题的时......
  • 解密Prompt45. 再探LLM Scalable Oversight -辩论、博弈哪家强
    之前我们已经介绍过几个针对ScalableOversight的解法,也就是当模型能力在部分领域超越人类标注者后,我们该如何继续为模型提供监督信号,包括持续提升Verifier的能力,辅助人类提供监督信号:self-Critic持续提升模型在弱监督下的泛化性:weak-to-strongGeneralization以上两个方向相......
  • AcWing 791:高精度加法 ← string+数组
    【题目来源】https://www.luogu.com.cn/problem/P1601https://www.acwing.com/problem/content/793/【题目描述】高精度加法,相当于a+bproblem,不用考虑负数。输入不含前导0。【输入格式】分两行输入。a,b≤10^500。【输出格式】输出只有一行,代表a+b的值。【输入样例】1......
  • 12.28 CW 模拟赛 赛时记录
    前言还是只管考试的策略,别想其他的每个题控制用时,根据时间选择策略,冷静看题完蛋了是\(\rm{NOIP}\),我们没救了\(\rm{T1}\)怎么办,像是很典的题但是我多半做不出来别人做过容斥的肯定会,但是我就不一样了\(\rm{T2}\)好像也不会做\(\rm{T3}\)基环树上的\(\rm......
  • 12.26 CW 模拟赛 T1. 平均
    思路首先你发现假设当前的平均数是\(a\),其中\(\lceila\rceil=k\),那么你势必要选上所有\(<k\)的数来拉低平均数,然后贪心的从小到大选\(\geqk\)的数来提高贡献如果想不到也可以这样想,对于一个确定的平均数,一定要尽可能的让比平均数小的数更多,才能更多的......