题意 Q个操作,将l,r 的值改为w
问最后1,n的sum 为多少
成段更新(通常这对初学者来说是一道坎),需要用到延迟标记(或者说懒惰标记),简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候
题意:O(-1)
思路:O(-1)
线段树功能:update:成段替换 (由于只query一次总区间,所以可以直接输出1结点的信息)
线段:1-N(题目天然给出)
区间和性质:求sum
重点在于如何设计一个lazy操作
#include <cstdio> #include <cstdlib> #include <cmath> #include <cstring> #include <ctime> #include <algorithm> #include <iostream> #include <sstream> #include <string> #define oo 0x13131313 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 const int maxn=100000+5; int CASE; using namespace std; int N,Q; int tree[maxn*4]; int col[maxn*4]; //延迟标记 void Pushup(int rt) //向上更新 { tree[rt]=tree[rt<<1]+tree[rt<<1|1]; } int build(int l,int r,int rt) //与以往差不多,注意延迟标记的重新赋值,有了build 一般不用memset初始化了 { col[rt]=0; if(l==r) {tree[rt]=1;return 0;} int m=(l+r)/2; build(lson); build(rson); Pushup(rt); } void Pushdown(int rt,int k) //k是长度 { if(col[rt]) { col[rt<<1]=col[rt<<1|1]=col[rt]; tree[rt<<1]=(k-(k>>1))*col[rt]; tree[rt<<1|1]=(k>>1)*col[rt]; col[rt]=0; } } int update(int L,int R,int c,int l,int r,int rt) { if (L<=l&&r<= R) { col[rt]=c; //不同题目处理方式不同,这里不属于下放操作,属于更新操作,与下放没有任何冲突关系 tree[rt]=c*(r-l+1); return 0; } Pushdown(rt,r-l+1); //Lazy 下放 int m=(l+r)>>1; //下面与以往一样 if (L<=m) update(L,R,c,lson); if (R>m) update(L,R,c,rson); Pushup(rt); } void solve() { int ll,rr,w; for(int i=1;i<=Q;i++) { scanf("%d%d%d",&ll,&rr,&w); update(ll,rr,w,1,N,1); } printf("Case %d: The total value of the hook is %d.\n",CASE,tree[1]); } int main() { int T; cin>>T; CASE=0; while(T--) { CASE++; cin>>N>>Q; build(1,N,1); solve(); } return 0; }