hdu 1698 Just a Hook (数据结构_线段树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698

 

题目大意:一题关于Dota的题,寂寞的男人玩Dota,空虚的男人做Dota题。言归正传,本题给定一个长度为n的序列,每个位置初始化都为1,现在有q个操作,可以将某段区间的数全部赋为1或2或3,问最后的序列总和是多少。

 

解题思路:很早之前用暴力的方法才能背后往前面操作过了这题,这种解法利用了某段区间如果在后面被操作过,那么前面的操作就无效,这样枚举每个i位置,看最后一次操作是变成1还是2还是3,如果没操作那就是默认1,用了203ms。

    前几天在金华邀请赛中碰到一题用线段树解的题目,是成段更新的,不会做。比赛完看了些文章,果断开始做这题成段更新入门题。第一次写成段更新的解题报告,写的详细些,后面有新的领悟,也都在这篇文章修改。单点更新是更新叶子节点,然后再从叶子一层一层往回更新到根,但是成段更新也这样的话复杂度太高,一些更新根本没必要,比如说很多情况下不必更新到叶子节点。这里引入lazy数组,表示这个节点是否可以延迟操作。如果可以延迟操作,那么本次更新就到此为止,不必更新子节点。如果下次要更新或者查询它的子节点再修改lazy值,然后更新子节点。傻仔(大二大三进总决赛,大四无奈退役的男人)概括了下:简单来说就是每次更新的时候不要更新到底,用延迟标记使得更新延迟到下次需要更新or询问到的时候。具体得实现是:在更新节点时,判断我们查询到的节点是否在题目要求的更新范围内,如果在则标记(改变lazy值),如果不在则判断这个节点在之前的操作中是否被标记,如果之前被标记,去除标记,将标记移到子节点中,因为子节点也是要被更新的,只是之前父节点被标记(用它丰厚的羽翼保护了子节点)。

    下面的这段代码是我在杭州用记事本敲得,没有编译器,只能通过hdu来判断写的是否正确,8A。后面在看别人解题报告时发现一个输入优化,因为每个输入的数都是整数,可以用getchar不用scanf,速度快了一半,具体见代码。

   

 

测试数据:

3
10
2
1 5 2
5 9 3

10
3
1 5 3
1 5 2
1 5 1

10
5
1 4 2
2 4 3
1 2 3
5 6 1
5 9 3


代码:

#include <stdio.h>
#include <string.h>
#define MAX 110000
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1


int n,sum[MAX*3];
int q,lazy[MAX*3];


void PushUp(int rt) {

	sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void build(int l,int r,int rt) {
	
	lazy[rt] = 0;
	if (l == r) {
		
		sum[rt] = 1;
		return;
	}
	int m = (l + r) >> 1;
	build(lson);
	build(rson);
	PushUp(rt);
}

void PushDown(int rt,int tot) {

	if (lazy[rt] != 0) {

		lazy[rt<<1] = lazy[rt<<1|1] = lazy[rt];
		sum[rt<<1] = lazy[rt] * (tot - (tot >> 1));
		sum[rt<<1|1] = lazy[rt] * (tot >> 1);
		lazy[rt] = 0;
	}
}
void update(int L,int R,int add,int l,int r,int rt) {

	if (l >= L && r <= R) {
	
		lazy[rt] = add;
		sum[rt] = add * (r - l + 1);
		return;
	}
	int m = (l + r) >> 1;
	PushDown(rt,r-l+1);
	if (m >= L) update(L,R,add,lson);
	if (m < R) update(L,R,add,rson);
	PushUp(rt);
}


int getval(){ 
   
	char c;
	int ret=0;
	while((c=getchar())!=' '&&c!='\n')
		ret=ret*10+(c-'0');    
	return ret;
}
int main()
{
	int i,j,k,t,cas = 0;
	

	t = getval();
	while (t--) {
		
		n = getval();
		build(1,n,1);
		q = getval();
		for (i = 1; i <= q; ++i) {

			int a,b,c;
			a = getval();
			b = getval();
			c = getval();
			update(a,b,c,1,n,1);
		}
		printf("Case %d: The total value of the hook is %d.\n",++cas,sum[1]);
	}
}


本文ZeroClock原创,但可以转载,因为我们是兄弟。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值