想分块想了很久一点思路都没有,结果一看都是写的线段树= = 。。。完全忘记了还有线段树这种操作
题意:给一个数组,一种操作是改变l到r为c,还有一种操作是查询l到r的总和差
线段树记得+lazy标记
#include<bits/stdc++.h> #define fi first #define se second #define mp make_pair #define pb push_back #define pii pair<int,int> #define C 0.5772156649 #define pi acos(-1.0) #define ll long long #define mod 998244353 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const double g=10.0,eps=1e-7; const int N=100000+10,maxn=sqrt(N)+100,inf=0x3f3f3f3f; ll color[N<<2],lazy[N<<2],sum[N<<2]; bool same[N<<2]; void changecolor(ll c,ll x,int l,int r,int rt)//x是改变的差值,c是上一个颜色 { same[rt]=1; sum[rt]+=x*(r-l+1); color[rt]=c; lazy[rt]+=x; } void pushup(int rt) { if(same[rt<<1]&&same[rt<<1|1]&&color[rt<<1]==color[rt<<1|1]) { same[rt]=1; color[rt]=color[rt<<1]; } else same[rt]=0; sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void pushdown(int l,int r,int rt) { if(lazy[rt]) { int m=(l+r)>>1; changecolor(color[rt],lazy[rt],ls); changecolor(color[rt],lazy[rt],rs); lazy[rt]=0; } } void build(int l,int r,int rt) { if(l==r) { color[rt]=l; same[rt]=1; sum[rt]=0; return ; } int m=(l+r)>>1; build(ls); build(rs); pushup(rt); } void update(int l,int r,int rt,int L,int R,ll x) { if(L<=l&&r<=R&&same[rt]) { changecolor(x,abs(x-color[rt]),l,r,rt); return ; } pushdown(l,r,rt); int m=(l+r)>>1; if(L<=m)update(ls,L,R,x); if(m<R)update(rs,L,R,x); pushup(rt); } ll query(int l,int r,int rt,int L,int R) { if(L<=l&&r<=R)return sum[rt]; pushdown(l,r,rt); int m=(l+r)>>1; ll ans=0; if(L<=m)ans+=query(ls,L,R); if(m<R)ans+=query(rs,L,R); return ans; } int main() { int n,m; scanf("%d%d",&n,&m); build(1,n,1); while(m--) { int x,y; ll z; scanf("%d",&x); if(x==1) { scanf("%d%d%lld",&x,&y,&z); update(1,n,1,x,y,z); } else { scanf("%d%d",&x,&y); printf("%lld\n",query(1,n,1,x,y)); } } return 0; } /******************** ********************/