题目连接
题意
- 就是开始有一个数组a,开始有∀i∈[1,n],ai=i,还有另一个数组b,开始有∀i∈[1,n],bi=0,初始化然后两种操作,第一种操作是先对于∀i∈[l,r],令b[i]=b[i]+∣x−a[i]∣,然后将[l,r]内的所有a数组的数变成x,第二种操作查询b数组的区间和
题解
- 神奇的分块,对于a数组,每个块打上标记表示这个块内所有数是否都相同,然后对于b数组,打上标记表示这个块所有位置的数都要加上多少,然后处理第一种操作的时候不完整的块暴力处理,完整的块里面如果标记一相同,那么O(1)更新数据,否则暴力修改所有b数组元素
- 复杂度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));
}
}
}