「CF444C」DZY Loves Colors【分塊】

題目連接

題意

  • 就是開始有一個數組aa,開始有i[1,n],ai=i\forall i \in [1,n], a_i=i,還有另一個數組bb,開始有i[1,n],bi=0\forall i \in [1,n], b_i=0,初始化然後兩種操作,第一種操作是先對於i[l,r]\forall i \in [l,r],令b[i]=b[i]+xa[i]b[i]=b[i]+|x-a[i]|,然後將[l,r][l,r]內的所有aa數組的數變成xx,第二種操作查詢bb數組的區間和

題解

  • 神奇的分塊,對於aa數組,每個塊打上標記表示這個塊內所有數是否都相同,然後對於bb數組,打上標記表示這個塊所有位置的數都要加上多少,然後處理第一種操作的時候不完整的塊暴力處理,完整的塊裏面如果標記一相同,那麼O(1)O(1)更新數據,否則暴力修改所有bb數組元素
  • 複雜度O(O(能過))

代碼

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+10;
const int smaxn=3005;
int n,m,opt,l,r,x;
namespace blocking{
    int tot,belong[maxn],siz[smaxn],block;  //分塊基本數據
    long long a[maxn],same[smaxn],sum[smaxn],mark[smaxn],b[maxn];                //解題數據
    inline void init(int n) {
        block=(int)sqrt((double)n);
        tot=n%block?(n/block+1):(n/block);
        for(int i=1;i<=n;i++) belong[i]=(i-1)/block+1;
        for(int i=1;i<=tot;i++) siz[i]=(min(i*block,n)-(i-1)*block);
    }
    inline void solve(int l,int r,long long val) {
        for(int i=l;i<=r;i++) {
            if(same[belong[i]]) {
                for(int j=(belong[i]-1)*block+1;j<=belong[i]*block;j++) a[j]=same[belong[i]];
                same[belong[i]]=0;
            }
            sum[belong[i]]+=abs(val-a[i]);
            b[i]+=abs(val-a[i]);
            a[i]=val;
        }
    }
    inline void update(int l,int r,long long val) {
        if(belong[r]-belong[l]<=1) {
            solve(l,r,val);
            return;
        }
        solve(l,belong[l]*block,val);
        for(int i=belong[l]+1;i<=belong[r]-1;i++) {
            if(!same[i]) solve((i-1)*block+1,i*block,val),same[i]=val;
            else {
                mark[i]+=abs(val-same[i]);
                sum[i]+=1LL*block*abs(val-same[i]);
                same[i]=val;
            }
        }
        solve((belong[r]-1)*block+1,r,val);
    }
 
    inline long long query(int l,int r) {
        long long ans=0;
        if(belong[r]-belong[l]<=1) {
            for(int i=l;i<=r;i++) ans+=b[i]+mark[belong[i]];
            return ans;
        }
        for(int i=l;i<=belong[l]*block;i++) ans+=b[i]+mark[belong[i]];
        for(int i=belong[l]+1;i<=belong[r]-1;i++) ans+=sum[i];
        for(int i=(belong[r]-1)*block+1;i<=r;i++) ans+=b[i]+mark[belong[i]];
        return ans;
    }
 
    inline void debug() {
        printf("block= %d, tot= %d\n",block,tot);
        for(int i=1;i<=n;i++) printf("%d%c",belong[i],i==n?'\n':' ');
    }
}
using namespace blocking;
 
int main()
{
    scanf("%d %d",&n,&m);init(n);
    for(int i=1;i<=n;i++) a[i]=i;
    for(int i=1;i<=m;i++) {
        scanf("%d",&opt);
        if(opt==1) {
            scanf("%d %d %d",&l,&r,&x);
            update(l,r,x);
        }else {
            scanf("%d %d",&l,&r);
            printf("%lld\n",query(l,r));
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章