Div 1.D 求调
  • 板块学术版
  • 楼主_Ch1F4N_
  • 当前回复6
  • 已保存回复6
  • 发布时间2023/1/24 18:01
  • 上次更新2023/10/24 03:11:16
查看原帖
Div 1.D 求调
520748
_Ch1F4N_楼主2023/1/24 18:01

写了 2h,死活过不去第 1313 个数据点,求调或者卡常。

#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;
}
2023/1/24 18:01
加载中...