P8969 幻梦 | Dream with Dynamic

Sol

好题!

注意到 popcount 操作会使数以 log 的速度变小,所以没有加操作的话我们就可以直接暴力维护。

但是注意到有加操作,考虑懒标记,先 popcount 后加。

当一个区间 popcount 之后,值域范围极小,所以考虑暴力对每一种数预处理 popcount。

这里其实可以用线段树但是我懒了,用了分块。

Code

#include <iostream>
#include <iomanip>
#include <cstdio>
#include <vector>
#include <stack>
#include <queue>
#include <bitset>
#include <map>
#include <set>
#include <unordered_map>
#include <unordered_set>
#include <cstring>
#include <sstream>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <cassert>
#include <chrono>
#include <random>
#define x first
#define y second
#define pb push_back
#define eb emplace_back
#define pf push_front
#define desktop "C:\\Users\\MPC\\Desktop\\"
#define IOS ios :: sync_with_stdio (false),cin.tie (0),cout.tie (0)
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair <int,int> PII;
const int dx[] = {1,0,-1,0},dy[] = {0,-1,0,1};
template <typename T1,typename T2> bool tomax (T1 &x,T2 y) {
    if (y > x) return x = y,true;
    return false;
}
template <typename T1,typename T2> bool tomin (T1 &x,T2 y) {
    if (y < x) return x = y,true;
    return false;
}
LL power (LL a,LL b,LL p) {
    LL ans = 1;
    while (b) {
        if (b & 1) ans = ans * a % p;
        a = a * a % p;
        b >>= 1;
    }
    return ans;
}
#define popcount(x) __builtin_popcountll (x)
int fastio = (IOS,0);
#define endl '\n'
#define puts(s) cout << s << endl
const int N = 300010,B = 1010;
int n,q;
LL a[N];
bool vis[51];
int pos[N];
struct block {
	int l,r;
	bool flag;
	int to[51];
	LL add;
	void push_down () {
		if (!flag) for (int i = l;i <= r;i++) a[i] += add;
		else for (int i = l;i <= r;i++) a[i] = to[a[i]] + add;
		flag = add = 0;
	}
	void opt_add (LL k) {
		add += k;
	}
	void opt_popcount () {
		if (!flag) {
			memset (vis,0,sizeof (vis));
			for (int i = l;i <= r;i++) {
				a[i] = popcount (a[i] + add);
				vis[a[i]] = true;
			}
			for (int i = 1;i <= 50;i++) {
				if (vis[i]) to[i] = i;
			}
		}
		else {
			for (int i = 1;i <= 50;i++) to[i] = popcount (to[i] + add);
		}
		add = 0,flag = true;
	}
}b[N];
void modify_add (int l,int r,int k) {
	int p = pos[l],q = pos[r];
	if (p == q) {
		b[p].push_down ();
		for (int i = l;i <= r;i++) a[i] += k;
	}
	else {
		for (int i = p + 1;i <= q - 1;i++) b[i].opt_add (k);
		b[p].push_down (),b[q].push_down ();
		for (int i = l;i <= b[p].r;i++) a[i] += k;
		for (int i = b[q].l;i <= r;i++) a[i] += k;
	}
}
void modify_popcount (int l,int r) {
	int p = pos[l],q = pos[r];
	if (p == q) {
		b[p].push_down ();
		for (int i = l;i <= r;i++) a[i] = popcount (a[i]);
	}
	else {
		for (int i = p + 1;i <= q - 1;i++) b[i].opt_popcount ();
		b[p].push_down (),b[q].push_down ();
		for (int i = l;i <= b[p].r;i++) a[i] = popcount (a[i]);
		for (int i = b[q].l;i <= r;i++) a[i] = popcount (a[i]);
	}
}
LL query (int x) {
	int p = pos[x];
	if (!b[p].flag) return a[x] + b[p].add;
	return b[p].to[a[x]] + b[p].add;
}
int main () {
	cin >> n >> q;
	for (int i = 1;i <= n;i++) cin >> a[i];
	for (int i = 1;i <= n;i++) pos[i] = (i - 1) / B + 1;
	for (int i = 1;(i - 1) * B + 1 <= n;i++) b[i].l = (i - 1) * B + 1,b[i].r = min (i * B,n);
	while (q--) {
		char op;
		cin >> op;
		if (op == 'A') {
			int l,r,k;
			cin >> l >> r >> k;
			modify_add (l,r,k);
		}
		else if (op == 'P') {
			int l,r;
			cin >> l >> r;
			modify_popcount (l,r);
		}
		else {
			int x;
			cin >> x;
			cout << query (x) << endl;
		}
	}
	return 0;
}
posted @   incra  阅读(10)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示