HDU1698【屠夫的钩子】
具体细节在代码里面,算是一个区间修改,点查询吧。
成段更新(通常这对初学者来说是一道坎),
需要用到延迟标记(或者说懒惰标记),
简单来说就是每次更新的时候不要更新到底,
用延迟标记使得更新延迟到下次需要更新or询问到的时候
#include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace std; #define lson rt<<1,l,m #define rson rt<<1|1,m+1,r const int maxn=100005; int n; int sum[maxn<<3]; int col[maxn<<3]; void Pushup(int rt) { sum[rt]=sum[rt<<1]+sum[rt<<1|1]; } void Pushdown(int rt,int m) { if(col[rt]) { col[rt<<1]=col[rt<<1|1]=col[rt]; sum[rt<<1]=(m-(m>>1))*col[rt]; sum[rt<<1|1]=(m>>1)*col[rt]; col[rt]=0;//大注意2. 一定得记得改回来。 } } void build(int rt,int l,int r) { sum[rt]=1; if(l==r) return; int m=(l+r)>>1; build(lson); build(rson); Pushup(rt); } void update(int ql,int qr,int ch,int rt,int l,int r) { if(ql<=l&&qr>=r) { col[rt]=ch; sum[rt]=ch*(r-l+1); return; } Pushdown(rt,r-l+1);//会执行这一步的前提是要修改的已经插入已经标记未传给子结点的 int m=(l+r)>>1; if(ql<=m) update(ql,qr,ch,lson); if(qr>m) update(ql,qr,ch,rson); Pushup(rt); } int main() { int case_num,qnum,a,b,c; scanf("%d",&case_num); for(int i=1;i<=case_num;i++) { //注意1.每次还真得memset,或在build里面加入 col[i]=0; memset(col,0,sizeof(col)); scanf("%d",&n); build(1,1,n); //printf("%d\n",sum[1]); scanf("%d",&qnum); while(qnum--) { scanf("%d%d%d",&a,&b,&c); update(a,b,c,1,1,n); //printf("~%d %d %d %d\n",sum[1],col[1],col[2],col[3]); } printf("Case %d: The total value of the hook is %d.\n",i,sum[1]); } return 0; }