HDU 1698 Just a Hook

题目大意:

        现有N(1 ≤ N ≤ 100,000)个数字,初始时都是1,从左到右编号为1 ~ N,现有只有一种操作"X Y Z”,表示将编号区间[X, Y]中的数字都改成Z(Z只能取1、2、3)。

        现有多个测例,测例数题中给出,每个测例中都给出N以及Q(0 ≤ Q ≤ 100,000)次操作,要求对于每个测例都输出最终整个序列中数字的总和。

题目链接

注释代码:

/*                                             
 * Problem ID : HDU 1698 Just a Hook 
 * Author     : Lirx.t.Una                                             
 * Language   : C                            
 * Run Time   : 500 ms                                             
 * Run Memory : 496 KB                                             
*/

#include <memory.h>
#include <stdio.h>

//勾刺的最大数量
#define	MAXN		100000

#define	LFT(T)		( (T) << 1 )
#define	RHT(T)		( LFT(T) | 1 )

char	seg[MAXN * 3];//线段树,只保存每个结点区间的类型
//0 --> 混合类型,花色
//1、2、3 --> 纯类型,纯色

void
update( int tree, int type, int cl, int cr, int lft, int rht ) {
	//将线段树结点tree的结点区间[lft, rht]对区间[cl, cr]的类型进行跟新
	//cl、cr为changing lft and rht
	//将[cl, cr]所在区间类型改为type
	
	int		mid;
	int		tl, tr;//type_lft and type_rht,左子结点的类型以及右子结点的类型
	
	//[lft, rht]显然是包含[cl, cr]的
	//因此如果大区间的type和小区间type一样则无需更新
	if ( type == seg[tree] ) return ;
	
	if ( lft == cl && cr == rht ) {//命中,直接覆盖type即可
		
		seg[tree] = type;
		return ;
	}

	//未命中
	
	if ( seg[tree] ) {//如果当前结点为纯色则必须将该色传递给子结点!!!
		
		seg[ LFT(tree) ] = seg[tree];
		seg[ RHT(tree) ] = seg[tree];
	}//如果当前结点本身就是花的,则其子结点以及孙子结点等保留了真正的染色情况
	//因此无需将0传递下去
	
	mid = ( lft + rht ) >> 1;
	if ( cr <= mid )
		update( LFT(tree), type, cl, cr, lft, mid );
	else if ( cl > mid )
		update( RHT(tree), type, cl, cr, mid + 1, rht );
	else {
		
		update( LFT(tree), type, cl, mid, lft, mid );
		update( RHT(tree), type, mid + 1, cr, mid + 1, rht );
	}
	
	//最后一定要更新当前结点的类型(及颜色)
	tl = seg[ LFT(tree) ];
	tr = seg[ RHT(tree) ];
	//如果两儿子都是纯色且相同,则表示当前结点被一种颜色完全覆盖
	//更新当前结点type的则在查询时本来查到当前结点就可以停止,否则
	//就必须再继续向下查询才能得到结果而使复杂度大于logN了
	if ( tl && tr && tl == tr ) seg[tree] = tl;
	else seg[tree] = 0;//如果两边有花色,或者两边是不同的纯色,都代表当前结点区间为花色
}

int
query( int tree, int lft, int rht ) {//查询tree结点区间[lft, rht]上颜色值的总和
	
	int		mid;
	
	if ( seg[tree] ) return ( rht - lft + 1 ) * seg[tree];//纯色
	
	//花色
	mid = ( lft + rht ) >> 1;
	return query( LFT(tree), lft, mid ) + query( RHT(tree), mid + 1, rht );//一直分解到纯色为止
}

int	
main() {
	
	int		t, iscn;
	int		n, m;//勾刺数以及操作数
	int		lft, rht, type;//临时变量
	
	int		i;//计数变量
	
	scanf("%d", &t);
	iscn = 0;
	
	while ( t-- ) {
		
		memset(seg, 1, sizeof(seg));//初始时都为纯色1
		
		scanf("%d%d", &n, &m);
		while ( m-- ) {
			
			scanf("%d%d%d", &lft, &rht, &type);
			update( 1, type, lft, rht, 1, n );
		}
		
		printf("Case %d: The total value of the hook is %d.\n",
			++iscn, query( 1, 1, n ));
	}
	
	return 0;
}
无注释代码:

#include <memory.h>
#include <stdio.h>

#define	MAXN		100000

#define	LFT(T)		( (T) << 1 )
#define	RHT(T)		( LFT(T) | 1 )

char	seg[MAXN * 3];

void
update( int tree, int type, int cl, int cr, int lft, int rht ) {

	int		mid;
	int		tl, tr;

	if ( type == seg[tree] ) return ;

	if ( lft == cl && cr == rht ) {
	
		seg[tree] = type;
		return ;
	}

	if ( seg[tree] ) {

		seg[ LFT(tree) ] = seg[tree];
		seg[ RHT(tree) ] = seg[tree];
	}

	mid = ( lft + rht ) >> 1;
	if ( cr <= mid )
		update( LFT(tree), type, cl, cr, lft, mid );
	else if ( cl > mid )
		update( RHT(tree), type, cl, cr, mid + 1, rht );
	else {
	
		update( LFT(tree), type, cl, mid, lft, mid );
		update( RHT(tree), type, mid + 1, cr, mid + 1, rht );
	}

	tl = seg[ LFT(tree) ];
	tr = seg[ RHT(tree) ];
	if ( tl && tr && tl == tr ) seg[tree] = tl;
	else seg[tree] = 0;
}

int
query( int tree, int lft, int rht ) {

	int		mid;

	if ( seg[tree] ) return ( rht - lft + 1 ) * seg[tree];

	mid = ( lft + rht ) >> 1;
	return query( LFT(tree), lft, mid ) + query( RHT(tree), mid + 1, rht );
}

int	
main() {

	int		t, iscn;
	int		n, m;
	int		lft, rht, type;

	int		i;

	scanf("%d", &t);
	iscn = 0;

	while ( t-- ) {
	
		memset(seg, 1, sizeof(seg));

		scanf("%d%d", &n, &m);
		while ( m-- ) {
		
			scanf("%d%d%d", &lft, &rht, &type);
			update( 1, type, lft, rht, 1, n );
		}

		printf("Case %d: The total value of the hook is %d.\n",
				++iscn, query( 1, 1, n ));
	}

	return 0;
}
单词解释:

cupreous:adj, 铜的,含铜的

metallic:adj, 金属的,含金属的

hook:n, 挂钩,吊钩

pudge:n,  矮胖的人

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值