您的位置:首页 > 其它

HDU 1698 Just a Hook(线段树-区间修改|区间查询)

2015-09-25 20:29 531 查看
该题是线段树区间修改和区间查询的模板题,需要仔细理解模板中的setv数组和sumv数组,sumv数组定义为:如果只执行结点o及其子孙结点中的setv操作,结点o对应区间中所有数只和。 setv数组就是所谓的懒惰标记,我们不是每次修改值都遍历所有涉及到的区间,而是在查询时用到了哪个setv值之时临时更新。

还有一些细节没有搞懂,明白之后再回来补充。

细节参见代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
#include<map>
using namespace std;
const int maxn = 100000 + 5;
int T,n,q,y11,y22,v,kase=0,_sum,sumv[3*maxn],setv[maxn*3];
void pushdown(int o) {
    int lc = o*2, rc = o*2+1;
    if(setv[o] >= 0) {
        setv[lc] = setv[rc] = setv[o];
        setv[o] = -1;
    }
}
void maintain(int o, int L, int R) {
    int lc = o*2, rc = o*2+1;
    sumv[o] = 0;
    if(R > L) {
        sumv[o] = sumv[lc] + sumv[rc];
    }
    if(setv[o]>=0) sumv[o] = setv[o]*(R-L+1);
}
void update(int o, int L, int R) {
    int lc = o*2, rc = o*2+1;
    if(y11 <= L && y22 >= R) {
        setv[o] = v;
    } else {
        pushdown(o);
        int M = L + (R-L)/2;
        if(y11 <= M) update(lc, L, M); else maintain(lc, L, M);
        if(y22 > M) update(rc, M+1, R); else maintain(rc, M+1, R);
    }
    maintain(o, L, R);
}
void query(int o, int L, int R) {
    if(setv[o] >= 0) {
        _sum += setv[o] * (min(R,y22)-max(L,y11)+1);
    } else if(y11 <= L && y22 >= R) {
        _sum += sumv[o];
    } else {
        int M = L + (R-L)/2;
        if(y11 <= M) query(o*2, L, M);
        if(y22 > M) query(o*2+1, M+1, R);
    }
}
int main() {
    scanf("%d",&T);
    while(T--) {
        scanf("%d%d",&n,&q);
        v = 1; y11 = 1; y22 = n;
        update(1,1,n);
        while(q--) {
            scanf("%d%d%d",&y11,&y22,&v);
            update(1,1,n);
        } _sum = 0;
        y11 = 1; y22 = n;
        query(1,1,n);
        printf("Case %d: The total value of the hook is %d.\n",++kase,_sum);
    }
    return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: