http://acm.hdu.edu.cn/showproblem.php?pid=1698
题目背景是dotA,题的大致意思是给一组棍子染色,不同的颜色有不同的值,执行一系列的区间染色后,问这组棍子的总值是多少。
采用线段树的做法,但是此题数据很大,如果每一次更新时,对每一个底层的节点都更新的话超时了。故只对需要的节点进行更新,经过参考网上的高手的代码,我知道了其中的一种,就是更新节点后,把更新节点之前的节点标记为不可用,这样,在最后统计的时候,只要统计那些不是不可用的节点的总值就可以了。
#include <stdio.h>
#define MAX 100005
typedef 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;
}