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;
}
标签:P8969,return,int,LL,Dynamic,popcount,幻梦,include,define
From: https://www.cnblogs.com/incra/p/18474948