CodeForces 444C 分块

 

题目链接:http://codeforces.com/problemset/problem/444/C

题意:给定一个长度为n的序列a[]。起初a[i]=i,然后还有一个色度的序列b[],起初b[i]=0。现在有2种操作:

1 l r x:区间染色,a[l],a[l+1]...a[r]变成x.同时b[l],b[l+1]...b[r]加上对应的|x-a[i]|值。

2 l r:统计区间和,统计区间b[l],b[l+1]...b[r]的和。

思路:线段树是比较常见的做法。考虑分块。每块维护一个lazy表示是否整块颜色都相同,Bsum表示块的b[i]总和.lazyb表示块的b[i]累加值的和。然后暴力维护即可。

 

#define _CRT_SECURE_NO_DEPRECATE
#include<stdio.h>  
#include<string.h>  
#include<cstring>
#include<algorithm>  
#include<queue>  
#include<math.h>  
#include<time.h>
#include<vector>
#include<iostream>
#include<map>
using namespace std;
typedef long long int LL;
const int MAXN = 100000 + 10;
int belong[MAXN], block, num, L[MAXN], R[MAXN];
int n, q;
LL a[MAXN],b[MAXN];
struct Node{
    LL lazy, Bsum,lazyb;
}Bval[400];
void build(){
    block = (int)sqrt(n + 0.5);
    num = n / block; if (n%block){ num++; }
    for (int i = 1; i <= num; i++){
        Bval[i].Bsum = 0; Bval[i].lazy = 0; Bval[i].lazyb=0;
        L[i] = (i - 1)*block + 1; R[i] = i*block;
    }
    R[num] = n;
    for (int i = 1; i <= n; i++){
        belong[i] = ((i - 1) / block) + 1;
    }
}
void modify(int st, int ed,int val){
    if (belong[st] == belong[ed]){
        if(Bval[belong[st]].lazy){
            for(int i=L[belong[st]];i<=R[belong[st]];i++){
                a[i]=Bval[belong[st]].lazy;
            }
            Bval[belong[st]].lazy=0;
        }
        for(int i=st;i<=ed;i++){
            Bval[belong[st]].Bsum+=abs(a[i]-val);
            b[i]+=abs(a[i]-val);
            a[i]=val;
        }
        return;
    }
    if(Bval[belong[st]].lazy){
        for(int i=L[belong[st]];i<=R[belong[st]];i++){
            a[i]=Bval[belong[st]].lazy;
        }
        Bval[belong[st]].lazy=0;
    }
    for (int i = st; i <= R[belong[st]]; i++){
        Bval[belong[st]].Bsum+=abs(val-a[i]);
        b[i]+=abs(val-a[i]);
        a[i]=val;
    }
    for (int i = belong[st] + 1; i < belong[ed]; i++){
        if(Bval[i].lazy){
            Bval[i].lazyb+=abs(val-Bval[i].lazy);
            Bval[i].Bsum+=(1LL*abs(Bval[i].lazy-val)*(R[i]-L[i]+1));
            Bval[i].lazy=val;
        }
        else{
            for(int j=L[i];j<=R[i];j++){
                b[j]+=abs(a[j]-val);
                Bval[i].Bsum+=abs(a[j]-val);
                a[j]=val;
            }
            Bval[i].lazy=val;
        }
    }
    if(Bval[belong[ed]].lazy){
        for(int i=L[belong[ed]];i<=R[belong[ed]];i++){
            a[i]=Bval[belong[ed]].lazy;
        }
        Bval[belong[ed]].lazy=0;
    }
    for (int i = L[belong[ed]]; i <= ed; i++){
        Bval[belong[ed]].Bsum+=abs(val-a[i]);
        b[i]+=abs(val-a[i]);
        a[i]=val;
    }
}
LL query(int st, int ed){
    LL ans = 0;
    if (belong[st] == belong[ed]){
        for (int i = st; i <= ed; i++){
            ans += (b[i]+Bval[belong[st]].lazyb);
        }
        return ans;
    }
    for (int i = st; i <= R[belong[st]]; i++){
        ans += (b[i]+Bval[belong[st]].lazyb);
    }
    for (int i = belong[st] + 1; i < belong[ed]; i++){ 
        ans += Bval[i].Bsum;
    }
    for (int i = L[belong[ed]]; i <= ed; i++){ 
        ans += (b[i]+Bval[belong[ed]].lazyb);
    }
    return ans;
}
int main(){
//#ifdef kirito
//    freopen("in.txt", "r", stdin);
//    freopen("out.txt", "w", stdout);
//#endif
//    int start = clock();
    while (~scanf("%d%d", &n,&q)){
        for (int i = 1; i <= n; i++){ a[i]=i; b[i]=0;}
        build();
        int type, l, r, v;
        for (int i = 1; i <= q; i++){
            scanf("%d", &type);
            if (type == 1){
                scanf("%d%d%d", &l, &r,&v);
                modify(l, r,v);
            }
            else{
                scanf("%d%d", &l, &r);
                printf("%lld\n", query(l, r));
            }
        }
    }
//#ifdef LOCAL_TIME
//    cout << "[Finished in " << clock() - start << " ms]" << endl;
//#endif
    return 0;
}

 

posted @ 2016-10-10 16:47  キリト  阅读(588)  评论(0编辑  收藏  举报