首页 > 其他分享 >Codeforces 1876G Clubstep.md

Codeforces 1876G Clubstep.md

时间:2023-12-29 21:01:56浏览次数:31  
标签:md log int top Codeforces fa maxn Clubstep maxp

首先考虑暴力的贪心。
从 \(r\) 到 \(l\) 依次遍历,若 \(a_i < x\) 则一直进行题目中的操作。
正确性是能保证的,因为选后面的 \(j\) 只能 \(+ 1\),而选 \(i\) 可以 \(+2\),且 \(i\) 前面的部分都是 \(+1\)。

考虑转化一下,把对 \(i\) 进行操作 \(k\) 次后,\(\forall j\in [1, i), a_j\leftarrow a_j + k\) 改为 \(x\leftarrow x - k\)。
可以发现这样肯定是不会影响答案的,而且这样就可以直接维护 \(x\) 的值了。

考虑用 \(f(i, x)\) 表示现在在 \(a_i\) 和 \(x\) 的值时满足 \([1, i]\) 都能满足题目所述的条件时的答案。
若 \(a_i\ge x\),则 \(f(i, x) = f(i - 1, x)\);否则 \(f(i, x) = i\times \lceil\frac{x - a_i}{2}\rceil + f(i - 1, \lfloor\frac{x + a_i}{2}\rfloor)\)。

考虑询问 \((l, r, x)\),那因为只需要满足 \([l, r]\) 就行了,就不需要满足 \([1, l)\)。
就找到 \(f(r, x)\) 递归到 \(i = l - 1\) 时的 \(x'\),\(f(r, x) - f(l - 1, x')\) 就是答案。

能够发现 \(f\) 的转移式子是一棵树,便考虑把这棵树建出来,就可以通过在到根的链上二分到对应的时间点。
优化一下,用个树剖就行了。

考虑对于 \(a_i\ge x\) 的节点,这个节点其实不会产生贡献,不如直接等到 \(j < i, a_j < x\) 时再建点。
优化完这个节点数就只有 \(O(q\log W)\)(\(W\) 是值域)了。
考虑 \(f(i, x_1), f(i, x_2), x_1 < x_2\),那么每走一步,\(x2 - x1\) 都会缩小一半,所以至多在 \(\log W\) 次后就会成为一个节点。

然后用个数据结构维护建树即可,注意常数。

时间复杂度 \(O(n\log q + q\log W\log q + q\log (q\log W))\)。

#include<bits/stdc++.h>
using i64 = long long;
using pii = std::pair<int, int>;
const int maxn = 3e5 + 10, maxp = maxn * 33;
int fa[maxp], ti[maxp], siz[maxp], son[maxp], top[maxp]; i64 sum[maxp]; int m;
std::vector<pii> es[maxp];
int a[maxn];
int ql[maxn], qr[maxn], qx[maxn], id[maxn];
std::vector<pii> inx[maxn];
int main() {
	int n; scanf("%d", &n);
	for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
	int q; scanf("%d", &q);
	for (int i = 1; i <= q; i++) scanf("%d%d%d", &ql[i], &qr[i], &qx[i]);
	for (int i = 1; i <= q; i++) inx[qr[i]].emplace_back(qx[i], i);
	std::priority_queue<pii> s; std::vector<pii> t;
	for (int i = n; i; i--) {
		for (pii j : inx[i]) s.emplace(j.first, id[j.second] = ++m);
		while (! s.empty() && s.top().first > a[i]) {
			int x = s.top().first, u = s.top().second; s.pop();
			int v = (x + a[i]) >> 1;
			if (t.empty() || t.back().first != v) t.emplace_back(v, ++m);
			fa[u] = t.back().second, sum[u] = 1ll * i * ((x + 1 - a[i]) >> 1), ti[u] = i;
		}
		while (! t.empty()) s.push(t.back()), t.pop_back();
	}
	m++, ti[m] = -1;
	while (! s.empty()) fa[s.top().second] = m, ti[s.top().second] = 0, s.pop();
	for (int i = m - 1; i; i--) sum[i] += sum[fa[i]];
	for (int i = 1; i < m; i++) siz[i]++, siz[fa[i]] += siz[i];
	for (int i = 1; i <= m; i++) siz[i] > siz[son[fa[i]]] && (son[fa[i]] = i);
	top[m] = m;
	for (int i = m - 1; i; i--) top[i] = i == son[fa[i]] ? top[fa[i]] : i;
	for (int i = m; i; i--) es[top[i]].emplace_back(ti[i], i);
	for (int i = 1; i <= q; i++) {
		int u = top[id[i]];
		while (ti[u] >= ql[i]) u = top[fa[u]];
		int w = std::lower_bound(es[u].begin(), es[u].end(), (pii){ql[i], 0}) - es[u].begin() - 1;
		printf("%lld\n", sum[id[i]] - sum[es[u][w].second]);
	}
	return 0;
}

标签:md,log,int,top,Codeforces,fa,maxn,Clubstep,maxp
From: https://www.cnblogs.com/rizynvu/p/17935671.html

相关文章

  • Codeforces Round 918 (Div. 4)赛后总结(前缀和)(set部分用法)
    CodeforcesRound918(Div.4)赛后总结a,b题没啥好说的c题典中典没开longlong一回事,还有判断数a是否为完全平方数直接用sqrt(a)\(^2\)=a的判断就可以d题经典字符串问题首先,我们以一个字符数组的形式存数据。再根据已知cv,cvc两种形式,我们只需要判断c的时候看v是否有用过(可......
  • Codeforces Round 887 (Div. 1)
    CodeforcesRound887(Div.1)A先来个二分。注意到这样一件事:考虑是\(a_i\)失效的最小时间\(t_i\),发现\(t\)有单调性。所以从大到小考虑\(a\),每次相当于将二分的值减去一个值,复杂度\(O(\sumn(\logn+\logk))\)。codeconstintN=2e5+10;intn;llk;lla......
  • Codeforces Round #843 (Div. 2)
    安利一个叫codeforcesbetter的插件  https://greasyfork.org/zh-CN/scripts/465777-codeforces-better今天装了后使用cf体验非常舒适=====A.GardenerandtheCapybaras(easyversion)问字符串s能否切分成3个字符串a、b、c,且满足a<=b&&c<=b或者b>=a&&b>=cs长度<=100,暴力......
  • [Codeforces] CF1538F Interesting Function
    CF1538FInterestingFunction题目传送门题意给定两个正整数\(l,r\)(\(l<r\)),将\(l\)不断加\(1\)直到\(l=r\),求出这一过程中\(l\)发生变化的位数总数。位数变化指:\(l=909\),将\(l+1\)后有\(2\)位数字发生变化。\(l=9\),将\(l+1\)后也有\(2\)位数字发生变......
  • codeforces比赛(1):codeforces 918_div4
    A、OddOneOut跳转原题点击此:A题地址1、题目大意  给你三个数,其中两个是相等的,问你还有一个不相等的数是多少。2、题目解析  直接暴力枚举即可,只要找到两个数相等,那么答案就是另一个数。#include<bits/stdc++.h>usingnamespacestd;intT;inta,b,c;voidsol......
  • 免费背景音人声分离解决方案MVSEP-MDX23,足以和Spleeter分庭抗礼
    在音视频领域,把已经发布的混音歌曲或者音频文件逆向分离一直是世界性的课题。音波混合的物理特性导致在没有原始工程文件的情况下,将其还原和分离是一件很有难度的事情。言及背景音人声分离技术,就不能不提Spleeter,它是一种用于音频源分离(音乐分离)的开源深度学习算法,由Deezer研究......
  • windows 创建自定义url协议 通过浏览器打开cmd
    打开regedit注册表编辑器找到HKEY_CLASSES_ROOT新建如下目录 ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------......
  • Codeforces Round 917 (Div. 2)
    A.LeastProduct存在\(a[i]=0\),\(min=0\),不需要任何操作。负数个数为偶数(包括0),\(min=0\),把任意一个改为\(0\)。负数个数为奇数,\(min=\proda[i]\),不需要任何操作。voidsolve(){ intn; cin>>n; vector<int>b,c,d; for(inti=0;i<n;++i){ in......
  • [Codeforces] CF1536C Diluc and Kaeya
    CF1536CDilucandKaeya题意题目传送门给你一个字符串\(S\),其中只包含'K'或'D'两种字符,要求划分这个字符串使得各部分的\(n(D):n(K)\)相同,其中\(n(D)\)表示\(S\)中字符'D'出现的个数,最大化划分后形成的组数。求出\(S\)的所有前缀中的上述答案。思路注意到,如......
  • 【Python数据分析课程设计】大数据分析—TMDB 电影数据集分析
    一、选题背景随着当今社会的发展,电影已经成为人们日常生活中不可或缺的一部分。人们通过观看电影来获得娱乐、放松、获取信息以及探索不同的文化和观点。在数字化时代,大量的电影数据被记录和存储,这为电影数据集的分析提供了丰富的资源。而如今,不同国家和地区的电影制作和发行公司......