写了 2h,死活过不去第 13 个数据点,求调或者卡常。
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int maxn = 3e5+1000;
const int maxw = 1000;
int warma;
int a[maxn];
int sum;//块的数量
inline int popcount(int x){
int cnt=0;
while(x!=0)
cnt+=(x&1),x>>=1;
return cnt;
}
class block{
public:
int l,r;//块的起止位置
int flag;//是否已经被 popcount 过
pair<int,int> chifan[maxw];
int tot;
//popcount 后块内不同元素数量至多 50 个,所以暴力记录查询
int tag;//没有被 popcount 前记录加了多少
void init();//初始化
void maintain();//散块重构
void change();//popcount 后转换记录方式
void add(int x);
void Pop();
}b[maxw];
inline void block::init(){
flag=0;
tot=0;
tag=0;
}
void block::maintain(){
if(flag==0){
for(int i=l;i<=r;i++) a[i]=a[i]+tag;
tag=0;
}
else{
for(int i=l;i<=r;i++)
{
for(int j=1;j<=tot;j++)
if(a[i]==chifan[j].first){
a[i]=chifan[j].second+tag;
break;
}
}
}
for(int i=1;i<=tot;++i) chifan[i].first=chifan[i].second=0;
flag=tot=tag=0;
}
void block::change(){
for(int i=l;i<=r;++i) a[i]+=tag;
tag=0;
flag=1;
map<int,int> use;
for(int i=l;i<=r;++i){
int op=0;
if(use[a[i]]==0)
chifan[++tot]=make_pair(a[i],popcount(a[i])),use[a[i]]=1;
}
}
inline void block::add(int x){
tag+=x;
}
void block::Pop(){
if(flag==0) change();
else{
for(int i=1;i<=tot;++i)
chifan[i].second=popcount(chifan[i].second+tag);
}
tag=0;
}
void changeA(int l,int r,int x){
int bl=l/warma+1;
if(l-l/warma*warma==0) bl--;
int br=r/warma+1;
if(r-r/warma*warma==0) br--;
for(int i=bl+1;i<br;++i)
b[i].add(x);
b[bl].maintain();
b[br].maintain();
if(bl!=br){
for(int i=l;i<=b[bl].r;++i) a[i]+=x;
for(int i=b[br].l;i<=r;++i) a[i]+=x;
}
else{
for(int i=l;i<=r;i++) a[i]+=x;
}
}
void changeB(int l,int r){
int bl=l/warma+1;
if(l-l/warma*warma==0) bl--;
int br=r/warma+1;
if(r-r/warma*warma==0) br--;
for(int i=bl+1;i<br;++i)
b[i].Pop();
b[bl].maintain();
b[br].maintain();
if(bl!=br){
for(int i=l;i<=b[bl].r;++i) a[i]=popcount(a[i]);
for(int i=b[br].l;i<=r;++i) a[i]=popcount(a[i]);
}
else{
for(int i=l;i<=r;++i) a[i]=popcount(a[i]);
}
}
int question(int x){
int pos=x/warma+1;
if(x-x/warma*warma==0) pos--;
if(b[pos].flag==0) return a[x]+b[pos].tag;
else{
for(int j=1;j<=b[pos].tot;++j)
if(a[x]==b[pos].chifan[j].first) return b[pos].chifan[j].second+b[pos].tag;
}
}
inline int read(){
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-48;ch=getchar();}
return x*f;
}
int n,q;
signed main(){
n=read();
q=read();
warma=sqrt(n);
for(int i=1;i<=n;i++){
a[i]=read();
}
for(int i=1;i<=n;i=i+warma){
b[++sum].l=i;
b[sum].r=min(n,i+warma-1);
b[sum].init();
}
for(int i=1;i<=q;i++){
char op;
op=getchar();
while(op<'A'||op>'Z')
op=getchar();
if(op=='A'){
int l,r,x;
l=read();
r=read();
x=read();
changeA(l,r,x);
}
else if(op=='P'){
int l,r;
l=read();
r=read();
changeB(l,r);
}
else{
int x;
x=read();
printf("%lld\n",question(x));
}
}
return 0;
}