Codeforces 444C 线段树 懒惰标记
前天晚上的CF比赛div2的E题,很明显一个线段树,当时还在犹豫复杂度的问题,因为他是区间修改和区间查询,肯定是要用到懒惰标记。
然后昨天真的是给这道题跪了,写了好久好久,。。。我本来是写了个add标记作为累加用,因为这个题目很明显是累加型的懒惰标记,但是后来不知道脑子怎么想的,又把add标记给删了,认为只要用一个set标记标注此时该树是否是连续相同的,如果是,则值就存在setv【rt】中,然后就开始了漫长的WA的过程,很明显,我这样是采用了覆盖性的懒惰标记,每次我pushdonw下去 还要先pushdonw下一层的,。。。如果真这么写 绝壁TL,不这么写 肯定WA,。。明显一个累加型的懒惰标记,硬是给我写跪了,其实我后来意识到了要用累加型的,可是就是想沿着这个思路 改好。。最后躺在床上一想,真的只能用累加型的懒惰标记
发现线段树的懒惰标记这一块真的还不熟练,各种容易出错。。。赶紧练
#include <iostream> #include <cstdio> #include <cstring> #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define LL __int64 using namespace std; const int N=100000+20; LL d[N<<2],cur[N<<2],flag[N<<2],add[N<<2]; int n,m; LL abs(LL x){ if (x<0) return -x; return x; } void build(int rt,int l,int r) { d[rt]=cur[rt]=flag[rt]=add[rt]=0; if (l>=r){ cur[rt]=l; flag[rt]=1; return; } int mid=(l+r)>>1; build(lson); build(rson); } void up(int rt,int l,int r) { d[rt]=d[rt<<1]+d[rt<<1|1]; if (flag[rt<<1] && flag[rt<<1|1] && cur[rt<<1]==cur[rt<<1|1]){ cur[rt]=cur[rt<<1]; flag[rt]=1; } else{ flag[rt]=0; } } void pushdown(int rt,int l,int r) { if (l>=r) return; int mid=(l+r)>>1; if (add[rt]>0){ d[rt<<1]+=add[rt]*(mid-l+1); d[rt<<1|1]+=add[rt]*(r-mid); add[rt<<1]+=add[rt]; add[rt<<1|1]+=add[rt]; add[rt]=0; } if (flag[rt]>0){ cur[rt<<1]=cur[rt<<1|1]=cur[rt]; flag[rt<<1]=flag[rt<<1|1]=1; } } void fix(int L,int R,LL v,int rt,int l,int r) { int mid=(l+r)>>1; if (L<=l && r<=R){ if (flag[rt]>0){ d[rt]+=abs(v-cur[rt])*(r-l+1); add[rt]+=abs(v-cur[rt]); cur[rt]=v; return; } } pushdown(rt,l,r); if (L<=mid) fix(L,R,v,lson); if (R>mid) fix(L,R,v,rson); up(rt,l,r); } LL query(int L,int R,int rt,int l,int r) { //pushdown(rt,l,r); if (L<=l && r<=R) return d[rt]; int mid=(l+r)>>1; pushdown(rt,l,r); LL ret1,ret2; ret1=ret2=0; if (L<=mid) ret1=query(L,R,lson); if (R>mid) ret2=query(L,R,rson); return ret1+ret2; } int main() { int op,a,b; LL c; while (scanf("%d%d",&n,&m)!=EOF) { build(1,1,n); while (m--) { scanf("%d",&op); if (op==1){ scanf("%d%d%I64d",&a,&b,&c); fix(a,b,c,1,1,n); } else{ scanf("%d%d",&a,&b); LL ans=query(a,b,1,1,n); printf("%I64d\n",ans); } } } return 0; }