「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));
        }
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章