hdu just a hook 线段树

在网上看到很多人写线段树的专题,我觉得线段树如此流行不仅仅是因为ACM题目里有它,而且它的实际应用价值也很高。

这道题的大意是你可以将钩子的某一段区间变为等级1(铜钩),等级2(银钩),或等级3(金钩)的钩子,问你在若干次变换后,整个钩子的值是多少。

我的想法是建一颗线段树,树的每一个节点保存有左右端点的值,这一段长度的等级(初值为0),没插入一条线段,就在插入的过程中判断经过的线段有没有被覆盖过(这就是为什么初值为0的原因),如果有被覆盖过,就把这条线段打破(就是将这条线段重新置为0,表示为没覆盖),然后再将待插入的线段继续往下更新,将打破的这条线段的余下部分更新下去(个人觉得这思路很挫。。。但是我只能想到这么做了。。。)。

比如说开始我把(1,10)的区间变为等级3,现在我要将(4,6)的区间变为等级2,那么我就先正常插入(4,6)这个线段,插入过程中先碰到(1,10)这个线段,发现这个线段已经被覆盖过了(不为0),就把(1,10)置为0,然后把(1,10)拆成3段(1,3)值为3,(4,6)值为2,(7,10)值为3,分别从当前位置插入这三条线段,直到插入的线段和遇到的线段表示的长度一致的时候就停下,并更新这一条线段。

#include<stdio.h>

struct SeqTree
{
	int l,r,v;
}a[400005];

int n;

void build(int l,int r,int pos)
{
	a[pos].l = l;
	a[pos].r = r;
	a[pos].v = 0;
	if(l == r)
		return ;
	int mid = (l + r) >> 1;
	build(l,mid,(pos << 1) + 1);
	build(mid + 1,r,(pos << 1) + 2);
}

void insert(int l,int r,int v,int pos)
{
	if(a[pos].l == l && a[pos].r == r)
	{
		a[pos].v = v;
		return ;
	}
	int mid = (a[pos].l + a[pos].r) >> 1;
	if(l > mid)
		insert(l,r,v,(pos << 1) + 2);
	else if(r <= mid)
		insert(l,r,v,(pos << 1) + 1);
	else
	{
		insert(l,mid,v,(pos << 1) + 1);
		insert(mid + 1,r,v,(pos << 1) + 2);
	}
	if(a[pos].v)
	{
		if(r < a[pos].r)
		{
			if(r >= mid)
				insert(r + 1,a[pos].r,a[pos].v,(pos << 1) + 2);
			else
			{
				insert(r + 1,mid,a[pos].v,(pos << 1) + 1);
				insert(mid + 1,a[pos].r,a[pos].v,(pos << 1) + 2);
			}
		}
		if(l > a[pos].l)
		{
			if(l <= mid + 1)
				insert(a[pos].l,l-1,a[pos].v,(pos << 1) + 1);
			else
			{
				insert(a[pos].l,mid,a[pos].v,(pos << 1) + 1);
				insert(mid + 1,l-1,a[pos].v,(pos << 1) + 2);
			}
		}
	}
	a[pos].v = 0;
}

int find(int p,int pos)
{
	if(a[pos].v)
		return a[pos].v;
	if(a[pos].r == a[pos].l)
		return a[pos].v?a[pos].v:1;
	int mid = (a[pos].l + a[pos].r) >> 1;
	if(p <= mid)
		return find(p,(pos << 1) + 1);
	else
		return find(p,(pos << 1) + 2);
}

int main()
{
	int T,l,r,q,v;
	scanf("%d",&T);
	for(int icase = 1;icase <= T;++icase)
	{
		scanf("%d%d",&n,&q);
		build(1,n,0);
		while(q--)
		{
			scanf("%d%d%d",&l,&r,&v);
			insert(l,r,v,0);			
		}
		int ans = 0;
		for(int i = 1;i <= n;++i)
			ans += find(i,0);
		printf("Case %d: The total value of the hook is %d.\n",icase,ans);
	}
	return 0;
}


猜你喜欢

转载自blog.csdn.net/a549875231/article/details/12098525