杭电hdu 1698 just a hook 线段树

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;
}


你可能感兴趣的:(杭电hdu 1698 just a hook 线段树)