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; }