【题目描述】
给定含有n个数的序列,初始状态每个数为1,然后有q个操作,每次改变某段区间的值,求最后的总和。
【思路】
线段树的成段更新,需要用到懒惰标记(lazy_tag)
考虑最朴素的办法,更新区间段的时候从上到下全部更新,但是这样做的话每次更新时间是O(n)的,肯定要TLE。
lazy_tag的思想就是,当更新到某个节点,并且需要更新的区间包含这个节点所代表的区间时,直接更改这个区间,并做懒惰标记,不再继续向下更新,当更新或者询问到这个节点的子节点时,将标记下传。这样做可以大大降低时间复杂度。
#include<cstdio> #define N 100010 #define lson l,mid,n<<1 #define rson mid+1,r,n<<1|1 using namespace std; int sum[N<<2],add[N<<2]; int build(int l,int r,int n){ add[n]=0; if(l==r) return sum[n]=1; int mid=(l+r)>>1; return sum[n]=build(lson)+build(rson); } void update(int ll,int rr,int aa,int l,int r,int n){ if(ll==l&&rr==r){ add[n]=aa; sum[n]=aa*(r-l+1); return; } int m=r-l+1; if(add[n]!=0){ add[n<<1]=add[n<<1|1]=add[n]; sum[n<<1]=add[n]*(m-(m>>1)); sum[n<<1|1]=add[n]*(m>>1); add[n]=0; } int mid=(l+r)>>1; if(rr<=mid) update(ll,rr,aa,lson); else if(ll>mid) update(ll,rr,aa,rson); else update(ll,mid,aa,lson),update(mid+1,rr,aa,rson); sum[n]=sum[n<<1]+sum[n<<1|1]; } int main(){ int t,n,q,x,y,z; scanf("%d",&t); int d=1; while(t--){ scanf("%d",&n); build(1,n,1); scanf("%d",&q); while(q--){ scanf("%d%d%d",&x,&y,&z); update(x,y,z,1,n,1); } printf("Case %d: The total value of the hook is %d.\n",d++,sum[1]); } return 0; }
浙公网安备 33010602011771号