P8421 [THUPC2022 决赛] rsraogps

考虑离线。

我们从小到大枚举 RR,考虑令 sis_ilil \leq i,且 r[l,R]r \in [l, R] 的答案。可以发现对于询问 l,rl,r,答案即为 srsl1s_r - s_{l-1}

接着我们考虑当 RR+1R \leftarrow R+1 时,对 ss 的影响。

RR+1R \leftarrow R+1,可以发现对于 sis_i,增加的贡献应该为 [i,R],[i1,R],,[1,R][i,R],[i-1,R],\cdots,[1,R] 的区间的价值之和。

可以发现,随着这个区间扩大,在 O(logv)O(\log v) 的次数内,按位与、按位或和 gcd\gcd 都会在某个区间 [p,R][p,R][p,R1][p,R-1] 相等。

那么往前,[p1,R],[p2,R],,[1,R][p-1,R],[p-2,R],\cdots,[1,R] 都会满足这样的性质。也就是贡献和上一次是一样的。

所以我们只需要暴力找到这个点 pp,然后对于 spsRs_p \sim s_R 暴力算贡献。

对于 s1sp1s_1 \sim s_{p-1},其贡献和上一次他被暴力算的贡献是一样的。只需要令 tit_iii 被暴力算的时间戳即可。

整体的复杂度应该是 O(nlogv)O(n \log v) 的。O(logv)O(\log v) 是暴力求 pp 的复杂度。

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
#include <string>
#include <numeric>
#include <vector>
using namespace std;

const int N = 5e6 + 5;

struct qer
{
	int l, id;
	qer(int _l, int _i) : l(_l), id(_i) {}
	qer() {}
};

int n, m;
int a[N], b[N], c[N];
long long ans[N], val[N], q[N];
const long long MOD = 1LL << 32LL;
unsigned int tm[N], idx;

#define qr(p) (val[p] + q[p] * (idx - tm[p]) % MOD) % MOD

unsigned int ne[N], h[N], id;
qer e[N];

struct ios {
	inline char read() {
		static const int IN_LEN = 4500000;
		static char buf[IN_LEN], * s, * t;
		return (s == t) && (t = (s = buf) + fread(buf, 1, IN_LEN, stdin)), s == t ? -1 : *s++;
	}
	template <typename _Tp> inline ios& operator >> (_Tp& x) {
		static char c11, boo;
		for (c11 = read(), boo = 0; !isdigit(c11); c11 = read()) {
			if (c11 == -1)return *this;
			boo |= c11 == '-';
		}
		for (x = 0; isdigit(c11); c11 = read())x = x * 10 + (c11 ^ '0');
		boo && (x = -x);
		return *this;
	}
}io;

int main()
{
	memset(h, -1, sizeof h);
	io >> n >> m;
	for (int i = 1; i <= n; i++) io >> a[i];
	for (int i = 1; i <= n; i++) io >> b[i];
	for (int i = 1; i <= n; i++) io >> c[i];
	for (int i = 1; i <= m; i++)
	{
		int l, r;
		io >> l >> r;
		e[id] = qer(l, i);
		ne[id] = h[r];
		h[r] = id++;
	}
	for (unsigned int i = 1; i <= n; i++)
	{
		unsigned int nowj = i;
		for (unsigned int j = i - 1; j >= 1; j--)
		{
			unsigned int na(a[j] & a[j + 1]), nb(b[j] | b[j + 1]), nc(__gcd(c[j], c[j + 1]));
			if (na == a[j] && nb == b[j] && nc == c[j]) break;
			nowj = j; // 找到 p 
			a[j] = na, b[j] = nb, c[j] = nc; // 后缀一段的答案 
		}
		val[i] = qr(i - 1);
		for (int j = nowj; j <= i; j++)
		{
			val[j] = qr(j); // 先算一次之前的贡献 
			q[j] = q[j - 1] + 1LL * a[j] * b[j] * c[j]; // 把累计贡献加上去 
			q[j] %= MOD;
			tm[j] = idx;
		}
		idx++; // 增加时间戳,以保证 a[j] * b[j] * c[j] 的贡献 
		for (int j = h[i]; ~j; j = ne[j])
		{
			qer k = e[j];
			ans[k.id] = (qr(i) - qr(k.l - 1) + MOD) % MOD;
		}
	}
	for (int i = 1; i <= m; i++) printf("%lld\n", ans[i]);
	return 0;
}
posted @   HappyBobb  阅读(15)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示