杭电hdu 1698 just a hook 线段树

来源:互联网 发布:郎酒2015销售额数据 编辑:程序博客网 时间:2024/05/29 08:46

http://acm.hdu.edu.cn/showproblem.php?pid=1698

题目背景是dotA,题的大致意思是给一组棍子染色,不同的颜色有不同的值,执行一系列的区间染色后,问这组棍子的总值是多少。

采用线段树的做法,但是此题数据很大,如果每一次更新时,对每一个底层的节点都更新的话超时了。故只对需要的节点进行更新,经过参考网上的高手的代码,我知道了其中的一种,就是更新节点后,把更新节点之前的节点标记为不可用,这样,在最后统计的时候,只要统计那些不是不可用的节点的总值就可以了。

#include <stdio.h>#define MAX 100005typedef struct _node{int left;int right;int count;}node;node no[MAX*3];int n, value;void insert(int l, int r, int i){no[i].left = l,no[i].right = r;no[i].count = 1;if(l==r){return ;}int mid = (l+r)/2;insert(l, mid, 2*i);insert(mid+1, r, 2*i+1);//no[i].count = no[i*2].count + no[2*i+1].count;}void modify(int start, int end, int i){if(no[i].count == value)return;//相同则不需要再更新if(no[i].left==start&&no[i].right==end){no[i].count = value;return;}//将改点标记为不可用点if(no[i].count!=-1){no[i*2].count=no[i*2+1].count=no[i].count;no[i].count=-1;}int mid = (no[i].left+no[i].right)/2;if(end <= mid){modify(start, end, i*2);}else if(start > mid){modify(start, end, 2*i+1);}else{modify(start, mid, i*2);modify(mid+1, end, 2*i+1);}}int search(int i)//统计总共有多少{if(no[i].count!=-1)return (no[i].right-no[i].left+1)*no[i].count;return search(2*i)+search(2*i+1);}int main(){//freopen("input.txt","r",stdin);int cas, t, i;int lf, rg, q;scanf("%d", &cas);for(t = 1; t <= cas; t ++){scanf("%d", &n);insert(1, n, 1);scanf("%d", &q);for(i = 1; i <= q; i ++){scanf("%d%d%d", &lf, &rg, &value);modify(lf, rg, 1);}printf("Case %d: The total value of the hook is %d.\n",t, search(1));}return 0;}