题意:长度为n的序列上有两种操作
0 ql qr 输出区间[ql,qr]和
1 ql qr v 区间[ql,qr]赋值为v
线段树懒标基础题,我用分块写了一个,在本题数据竟然跑的飞快
#include<iostream>
#include<cstdio>
#include<cmath>
#define rep(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=1e5+5;
typedef long long ll;
int val[maxn],belong[maxn],l[maxn],r[maxn],inv[maxn];
ll ans[maxn];
int n,q,op,ql,qr,v,cnt,block;
void update(int L,int R,int bt){
if(L==l[bt]&&R==r[bt]){
inv[bt]=v;ans[bt]=(ll)v*(R-L+1);
return ;
}
if(inv[bt]){
rep(i,l[bt],L-1)val[i]=inv[bt];
rep(i,R+1,r[bt])val[i]=inv[bt];
rep(i,L,R)ans[bt]+=v-inv[bt],val[i]=v;
inv[bt]=0;
return ;
}
rep(i,L,R)ans[bt]+=v-val[i],val[i]=v;
}
void update(){
int b1=belong[ql],b2=belong[qr];
if(b1==b2)update(ql,qr,b1);
else{
update(ql,r[b1],b1);b1++;
while(b1<b2)
update(l[b1],r[b1],b1),b1++;
update(l[b2],qr,b2);
}
}
ll query(int L,int R,int bt){
if(l[bt]==L&&r[bt]==R)return ans[bt];
if(inv[bt])return (ll)inv[bt]*(R-L+1);
ll res=0;
rep(i,L,R)res+=val[i];
return res;
}
ll query(){
ll res=0;
int b1=belong[ql],b2=belong[qr];
if(b1==b2)return query(ql,qr,b1);
res+=query(ql,r[b1],b1);b1++;
while(b1<b2)res+=ans[b1++];
res+=query(l[b2],qr,b2);
return res;
}
void init(){
block=sqrt(n);cnt=n/block;
rep(i,0,n-1){
belong[i]=i/block;
ans[belong[i]]+=val[i];
}
rep(i,0,cnt-1)l[i]=i*block,r[i]=(i+1)*block-1;
if(n%block){
l[cnt]=cnt*block,r[cnt]=n-1;cnt++;
}
}
int main(){
scanf("%d",&n);
rep(i,0,n-1)scanf("%d",val+i);
init();
scanf("%d",&q);
while(q--){
scanf("%d%d%d",&op,&ql,&qr);
ql--;qr--;
if(op){
scanf("%d",&v);
update();
}
else
printf("%lld\n",query());
}
return 0;
}