444 C DZY Loves Colors

来源:互联网 发布:php手册 pdf 编辑:程序博客网 时间:2024/05/17 21:42
/* 线段树,注意传递参数的写法 */#include <cstdio>#include <algorithm>using namespace std;#define LL long longconst int maxn = 1e5 + 10;LL lazy[maxn<<2];LL delta[maxn<<2];//代表一个根节点的历史改变量之和,解决一个区间被多次覆盖的问题LL sum[maxn<<2];//保存答案LL cal(LL x){    return x<0 ? -x:x;}void build(int l,int r,int rt){    if(l==r)    {        lazy[rt]=l;        return;    }    int mid=(l+r)>>1;    build(l,mid,rt<<1);    build(mid+1,r,rt<<1|1);    lazy[rt]=0;}void clear(int v,int l,int r,int rt)//clear函数清空当前节点的标记,并且更新维护的节点的信息{    if(lazy[rt]>0)    {        delta[rt]+=cal(v-lazy[rt]);        sum[rt]+=(r-l+1)*cal(v-lazy[rt]);    }    else    {        int mid=(l+r)>>1;        clear(v,l,mid,rt<<1);//清空子结点的值并且将子结点的值更新为正确值        clear(v,mid+1,r,rt<<1|1);        sum[rt]=sum[rt<<1]+sum[rt<<1|1]+delta[rt]*(r-l+1);//根据更新后的子结点的值更新父节点的值    }}void update(int L,int R,int v,int l,int r,int rt){    if(L<=l&&r<=R)    {        clear(v,l,r,rt);//是为了在这次覆盖之前,重新结算该节点的信息,并维护子结点的信息        lazy[rt]=v;        return;    }    if(lazy[rt]>0)    {        lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];    }    int mid=(l+r)>>1;    if(L<=mid)  update(L,R,v,l,mid,rt<<1);    if(R>mid)   update(L,R,v,mid+1,r,rt<<1|1);    lazy[rt]=0;    sum[rt]=sum[rt<<1]+sum[rt<<1|1]+delta[rt]*(r-l+1);}LL query(int L,int R,int l,int r,int rt){    if(L<=l&&r<=R)    {        return sum[rt];//只有当节点被覆盖时才直接返回    }    int mid = (l+r)>>1;    if(R<=mid)  return  query(L,R,l,mid,rt<<1)+delta[rt]*(R-L+1);//关键,此时对节点并不更新子结点的值,只是在不断下行的过程中,根据父节点的delta值更新答案    if(L>mid)   return query(L,R,mid+1,r,rt<<1|1)+delta[rt]*(R-L+1);    return query(L,mid,l,mid,rt<<1)+query(mid+1,R,mid+1,r,rt<<1|1)+delta[rt]*(R-L+1);}int main(){    int n,m;    scanf("%d%d",&n,&m);    build(1,n,1);    while(m--)    {        int op;        scanf("%d",&op);        int l,r,x;        if(op==1)        {            scanf("%d%d%d",&l,&r,&x);            update(l,r,x,1,n,1);        }        else        {            scanf("%d%d",&l,&r);            printf("%lld\n",query(l,r,1,n,1));        }    }    return 0;}

0 0