线段树剪枝 当区间内只有一种颜色时才进行更新 虽然乍一看对复杂度不是很好 仔细想想 虽然每次把一段区间染成同一种颜色 但以后再访问这一段里的区间时就可以直接返回
#include <bits/stdc++.h>
using namespace std;
#define ll long long
struct node
{
int l;
int r;
ll val;
ll clr;
ll laz;
};
node tree[400010];
int n,q;
void pushup(int cur)
{
tree[cur].val=tree[2*cur].val+tree[2*cur+1].val;
if(tree[2*cur].clr!=0&&tree[2*cur+1].clr!=0&&tree[2*cur].clr==tree[2*cur+1].clr)
{
tree[cur].clr=tree[2*cur].clr;
}
else tree[cur].clr=0;
}
void pushdown(int cur)
{
if(tree[cur].laz!=0)
{
tree[2*cur].val+=(tree[2*cur].r-tree[2*cur].l+1)*tree[cur].laz;
tree[2*cur].clr=tree[cur].clr;
tree[2*cur].laz+=tree[cur].laz;
tree[2*cur+1].val+=(tree[2*cur+1].r-tree[2*cur+1].l+1)*tree[cur].laz;
tree[2*cur+1].clr=tree[cur].clr;
tree[2*cur+1].laz+=tree[cur].laz;
tree[cur].laz=0;
}
}
void build(int l,int r,int cur)
{
int m;
tree[cur].l=l;
tree[cur].r=r;
tree[cur].val=0;
tree[cur].clr=0;
tree[cur].laz=0;
if(l==r)
{
tree[cur].clr=l;
return;
}
m=(l+r)/2;
build(l,m,2*cur);
build(m+1,r,2*cur+1);
pushup(cur);
}
void update(int pl,int pr,ll clr,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr&&tree[cur].clr!=0)
{
tree[cur].val+=(tree[cur].r-tree[cur].l+1)*(ll)abs(tree[cur].clr-clr);
tree[cur].laz+=(ll)abs(tree[cur].clr-clr);
tree[cur].clr=clr;
return;
}
pushdown(cur);
if(pl<=tree[2*cur].r) update(pl,pr,clr,2*cur);
if(pr>=tree[2*cur+1].l) update(pl,pr,clr,2*cur+1);
pushup(cur);
}
ll query(int pl,int pr,int cur)
{
ll res;
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
return tree[cur].val;
}
pushdown(cur);
res=0;
if(pl<=tree[2*cur].r) res+=query(pl,pr,2*cur);
if(pr>=tree[2*cur+1].l) res+=query(pl,pr,2*cur+1);
return res;
}
int main()
{
ll clr;
int i,op,l,r;
scanf("%d%d",&n,&q);
build(1,n,1);
while(q--)
{
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%lld",&l,&r,&clr);
update(l,r,clr,1);
}
else
{
scanf("%d%d",&l,&r);
printf("%lld\n",query(l,r,1));
}
}
return 0;
}