分块求调/kel

P2801 教主的魔法

Terraria @ 2021-04-26 13:50:35

1 #2 #3 #10 AC;

4 #5 #6 #9 WA;

7 #8 TLE。

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,q,size,cnt;//size表示完整的块的大小,cnt表示总共cnt个块
int a[1000009],b[1000009];
int in[1000009];//属于哪个块
int L[1000009],R[1000009];//每个块的左右端点
int add[1000009];
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<<1)+(x<<3)+(ch^48),ch=getchar();
    return x*f;
}
inline void write(int x){//快写
    if(x<0) x=~x+1,putchar('-');
    if(x>9) write(x/10);
    putchar(x%10+'0');
}
void init(){
    size=sqrt(n);
    cnt=n/size;
    if(n%size) cnt++;
    for(int i=1;i<=cnt;i++){
        L[i]=(i-1)*size+1;
        R[i]=i*size;
    }
    R[cnt]=n;
    for(int i=1;i<=n;i++){
        in[i]=i/size+1;
        b[i]=a[i];
    }
    for(int i=1;i<=cnt;i++) sort(b+L[i],b+R[i]+1);
}
void update(int l,int r,int k){
    int p=in[l],q=in[r];
    if(p==q){
        for(int i=l;i<=r;i++) a[i]+=k;
        for(int i=L[p];i<=R[q];i++) b[i]=a[i];
        sort(b+L[p],b+R[p]+1);
        return;
    }
    //处理左边的零散块
    for(int i=l;i<=R[p];i++) a[i]+=k;
    for(int i=L[p];i<=R[p];i++) b[i]=a[i];
    sort(b+L[p],b+R[p]+1);

    //处理右边的零散块
    for(int i=L[q];i<=r;i++) a[i]+=k;
    for(int i=L[q];i<=R[q];i++) b[i]=a[i];
    sort(b+L[q],b+R[q]+1);

    //处理中间完整的块
    for(int i=L[p]+1;i<=R[q]-1;i++) add[i]+=k;
}
int query(int l,int r,int k){
    int p=in[l],q=in[r],ans=0;
    if(p==q){
        for(int i=l;i<=r;i++){
            if(a[i]+add[q]>=k) ans++;
        }
        return ans;
    }
    for(int i=l;i<=R[p];i++){
        if(add[p]+a[i]>=k) ans++;
    }
    for(int i=L[q];i<=r;i++){
        if(add[q]+a[i]>=k) ans++;
    }
    for(int i=p+1;i<=q-1;i++){
        int ll=L[i],rr=R[i],tot=0;
        while(ll<=rr){
            int mid=(ll+rr)/2;
            if(b[mid]+add[i]>=k){
                rr=mid-1;
                tot=R[i]-mid+1;
            }
            else ll=mid+1;
        }
        ans+=tot;
    }
    return ans;
}
signed main(){
    n=read(),q=read();
    for(int i=1;i<=n;i++) a[i]=read();
    init();
    while(q--){
        char ch;
        int l,r,k;
        cin>>ch;
        l=read(),r=read(),k=read();
        if(ch=='M') update(l,r,k);
        if(ch=='A') write(query(l,r,k)),putchar('\n');
    }
}

by Terraria @ 2021-04-26 13:51:37

1 2 3 10 AC;

4 5 6 9 WA;

7 8 TLE。


by 日居月诸 @ 2021-04-26 14:07:43

    for(int i=1;i<=n;i++){
        in[i]=i/size+1;
        b[i]=a[i];
    }

显然应该写 in[i] = (i-1)/size + 1

另外,这里建议修改的时候归并哦


by Terraria @ 2021-04-26 16:54:40

@日居月诸 改完 in[i]=(i-1)/size+1 后60分了,两个TLE还有(


by Terraria @ 2021-04-26 17:10:04

谢谢!已AC,此贴完结


|