CF878E Numbers on the blackboard 题解

首先有一个很重要的观察:最后每一个 \(i\) 对答案的贡献为 \(a_i \times 2^{k_i}\),且 \(k\) 满足 \(k_1=0,k_{i,i>1} \ge 1,k_i \le k_{i-1}+1\)

考虑贪心。若 \(a_i \ge 0\),则让 \(k_i=k_{i-1}+1\),否则让 \(k_i=0\)。也就是说我们把序列分成了一些段,每段的 \(k\) 都形如 \(1,2,\dots,x\)

但是很显然这样的贪心是错的,比如 \(\{100,100,-1,100\}\)。最优解应该只分为一段,而这样贪心会分为两段。那如何改进呢。其实很简单,如果有一段的值是 \(\ge 0\) 的,那直接将这一段和前一段合并一定更优(这一段的系数变大),否则一定更劣。

怎么实现呢?我们可以先将询问离线下来并挂到右端点上。从左到右扫的过程中直接用并查集维护每一段,而 \([l,r]\) 只有最前面的一段可能不完整,这部分可以用类似哈希的做法求值。对于完整的几段可以用前缀和维护。

//dzzfjldyqqwsxdhrdhcyxll
#include <bits/stdc++.h>
using namespace std;
#define int long long
const int MAXN = 1e5 + 10;
const int mod = 1e9 + 7;
typedef pair <int,int> pii;
vector <pii> v[MAXN];
int n,Q,a[MAXN],p[MAXN],h[MAXN],fa[MAXN] 
int ans[MAXN],sum[MAXN],siz[MAXN],s[MAXN],val[MAXN];;
inline int Find(int x) {
	if(x == fa[x]) return x;
	return fa[x] = Find(fa[x]);
}
inline int Query(int l,int r) {
	return (h[l] - h[r + 1] * p[r - l + 1] % mod + mod) % mod;
}
signed main() {
	cin >> n >> Q;
	for(int i = 1;i <= n;i++) cin >> a[i]; 
	p[0] = 1;
	for(int i = 1;i <= n;i++) 
		s[i] = a[i],siz[i] = 1,
		val[i] = (a[i] % mod + mod) % mod,
		p[i] = p[i - 1] * 2 % mod;
	for(int i = n;i >= 1;i--) 
		h[i] = (h[i + 1] * 2 + a[i]) % mod;
	for(int i = 1;i <= n;i++) fa[i] = i;
	for(int i = 1,l,r;i <= Q;i++) 
		cin >> l >> r,
		v[r].emplace_back(make_pair(l,i));
	for(int i = 1;i <= n;i++) {
		while(Find(i) != 1 && s[Find(i)] >= 0) {
			int x = Find(i);
			int y = Find(Find(i) - 1);
			fa[x] = y;
			if((s[x] != 0 && siz[y] > 40) || (s[y] + s[x] * p[siz[y]] > 1e10)) s[y] = 1e10;
			else s[y] = s[y] + s[x] * p[siz[y]];
			val[y] = (val[y] + val[x] * p[siz[y]] % mod) % mod;
			siz[y] += siz[x];
		}
		sum[Find(i)] = (sum[Find(Find(i) - 1)] + val[Find(i)]) % mod;
		for(pii j : v[i]) {
			int l = j.first,id = j.second;
			ans[id] = 2 * (sum[Find(i)] - sum[Find(l)] + mod) % mod;
			ans[id] = (ans[id] + Query(l,Find(l) + siz[Find(l)] - 1)) % mod;
		}
	}
	for(int i = 1;i <= Q;i++) 	
		cout << (ans[i] + mod) % mod << endl;
	return 0;
}
posted @ 2024-10-11 21:20  Creeper_l  阅读(7)  评论(0编辑  收藏  举报
  1. 1 イエスタデイ(翻自 Official髭男dism) 茶泡饭,春茶,kobasolo
  2. 2 世间美好与你环环相扣 柏松
  3. 3 True love tired
  4. 4 一笑江湖 (DJ弹鼓版) 闻人听書_
  5. 5 最好的安排 曲婉婷
  6. 6 星星在唱歌 司南
  7. 7 山川 李荣浩
  8. 8 On My Way Alan Walker
  9. 9 百战成诗 王者荣耀·100英雄官方群像献礼歌
  10. 10 雪 Distance Capper / 罗言
  11. 11 Edamame bbno$ / Rich Brian
  12. 12 半生雪 七叔-叶泽浩
  13. 13 Catch My Breath Kelly Clarkson
  14. 14 Love Is Gone SLANDER / Dylan Matthew
  15. 15 Endless Summer Alan Walker / Zak Abel
  16. 16 悬溺 葛东琪
  17. 17 风吹丹顶鹤 葛东琪
  18. 18 Normal No More TYSM
  19. 19 哪里都是你 队长
  20. 20 Stronger Kelly Clarkson
  21. 21 廖俊涛
  22. 22 消愁 毛不易
  23. 23 The Runner Yubik
  24. 24 踏山河 七叔-叶泽浩
  25. 25 Waiting For Love Avicii
  26. 26 在你的身边 盛哲
  27. 27 Dream It Possible Delacey
  28. 28 凄美地 郭顶
  29. 29 满天星辰不及你 ycc
  30. 30 侧脸 于果
  31. 31 阿拉斯加海湾 蓝心羽
  32. 32 虞兮叹 闻人听書_
  33. 33 离别开出花 就是南方凯
  34. 34 盗墓笔记·十年人间 李常超 (Lao乾妈)
半生雪 - 七叔-叶泽浩
00:00 / 00:00
An audio error has occurred, player will skip forward in 2 seconds.