HDU - 1698 Just a Hook (线段树区间改值)

In the game of DotA, Pudge’s meat hook is actually the most horrible thing for most of the heroes. The hook is made up of several consecutive metallic sticks which are of the same length. 



Now Pudge wants to do some operations on the hook. 

Let us number the consecutive metallic sticks of the hook from 1 to N. For each operation, Pudge can change the consecutive metallic sticks, numbered from X to Y, into cupreous sticks, silver sticks or golden sticks. 
The total value of the hook is calculated as the sum of values of N metallic sticks. More precisely, the value for each kind of stick is calculated as follows: 

For each cupreous stick, the value is 1. 
For each silver stick, the value is 2. 
For each golden stick, the value is 3. 

Pudge wants to know the total value of the hook after performing the operations. 
You may consider the original hook is made up of cupreous sticks. 

Input

The input consists of several test cases. The first line of the input is the number of the cases. There are no more than 10 cases. 
For each case, the first line contains an integer N, 1<=N<=100,000, which is the number of the sticks of Pudge’s meat hook and the second line contains an integer Q, 0<=Q<=100,000, which is the number of the operations. 
Next Q lines, each line contains three integers X, Y, 1<=X<=Y<=N, Z, 1<=Z<=3, which defines an operation: change the sticks numbered from X to Y into the metal kind Z, where Z=1 represents the cupreous kind, Z=2 represents the silver kind and Z=3 represents the golden kind. 

Output

For each case, print a number in a line representing the total value of the hook after the operations. Use the format in the example. 

Sample Input

1
10
2
1 5 2
5 9 3

Sample Output

Case 1: The total value of the hook is 24.

 

题意:

有n个金属棒,金属棒的材质可以是金、银、铜分别对应着3、2、1的价值。

给出m个询问,每次可以将区间[a,b]内的金属棒价值更新,统计最后所有金属棒的总价值。

 

解题思路:
通过这道题总结出了区间改值的模板,区间改值和区间加值的区别就是往下传值的时候,区间加值需要加上需要加的值,区间改值则直接更新需要更新的值即可,在实现的时候可以使用不同的取值区别开,比如区间加值的时候用0作为标记,区间改值的时候用-1作为标记(因为可以直接使用memset初始化)

 

另外,最后树的根结点的值就是总区间的和。

 

AC代码:

#include<bits/stdc++.h>
using namespace std;

struct node
{
    int l,r,w,lazy;//tree的l,r表示数组区间[l,r],w表示[l,r]区间和 
}tree[400001];

//lazy!=0是加值,lazy!=-1是改值 

void build(int v,int l,int r)//建树,v表示tree里第v个结点,tree是完全二叉树 
{
    tree[v].l=l;
	tree[v].r=r;
    if(tree[v].l==tree[v].r)
    {
        tree[v].w=1; 
        return;
    }
    int mid=(l+r)/2;
    build(v*2,l,mid);
    build(v*2+1,mid+1,r);
    tree[v].w=tree[v*2].w+tree[v*2+1].w;
}

//void downadd(int v)//加值 标记下传 
//{
//    tree[v*2].lazy+=tree[v].lazy;
//    tree[v*2+1].lazy+=tree[v].lazy;
//    tree[v*2].w+=tree[v].lazy*(tree[v*2].r-tree[v*2].l+1);
//    tree[v*2+1].w+=tree[v].lazy*(tree[v*2+1].r-tree[v*2+1].l+1);
//    tree[v].lazy=0;
//}

void downupdate(int v)//改值 标记下传 
{
    tree[v*2].lazy=tree[v].lazy;
    tree[v*2+1].lazy=tree[v].lazy;
    tree[v*2].w=tree[v].lazy*(tree[v*2].r-tree[v*2].l+1);
    tree[v*2+1].w=tree[v].lazy*(tree[v*2+1].r-tree[v*2+1].l+1);
    tree[v].lazy=-1;
}


//int ask_point(int v,int x)//单点查询
//{
//    if(tree[v].l==tree[v].r)
//    {
//        return tree[v].w;
//    }
//    
//    //if(tree[v].lazy!=0) downadd(v);
//    if(tree[v].lazy!=-1) downupdate(v);
//    
//    int mid=(tree[v].l+tree[v].r)/2;
//    if(x<=mid) ask_point(v*2,x);
//    else ask_point(v*2+1,x);
//}

//void change_point(int v,int x,int y)//单点修改,a[x]改为y(或加减等操作) 
//{
//    if(tree[v].l==tree[v].r)
//    {
//        //tree[k].w+=y;
//        tree[v].w=y; //找到了x这个点,a[x]=y,也可进行其他操作 
//        return;
//    }
//    //if(tree[v].lazy!=0) downadd(v);
//    if(tree[v].lazy!=-1) downupdate(v);
//    
//    int mid=(tree[v].l+tree[v].r)/2;
//    if(x<=mid) change_point(v*2,x,y);
//    else change_point(v*2+1,x,y);
//    
//    tree[v].w=tree[v*2].w+tree[v*2+1].w; 
//}

//int ask_interval(int v,int a,int b)//区间查询[a,b]
//{
//    if(tree[v].l>=a&&tree[v].r<=b) 
//    {
//        return tree[v].w;
//    }
//    
//    //if(tree[v].lazy!=0) downadd(v);
//    if(tree[v].lazy!=-1) downupdate(v);
//    
//    int sum=0;
//    int mid=(tree[v].l+tree[v].r)/2;
//    if(a<=mid) sum+=ask_interval(v*2,a,b);
//    if(b>mid) sum+=ask_interval(v*2+1,a,b);
//    
//    return sum;
//}

//void changeadd_interval(int v,int a,int b,int y)//区间加值,[a,b]内所有数同时+y 
//{
//    if(tree[v].l>=a&&tree[v].r<=b)
//    {
//        tree[v].w+=(tree[v].r-tree[v].l+1)*y;
//        tree[v].lazy+=y;
//        return;
//    }
//    if(tree[v].lazy!=0) downadd(v);
//    //if(tree[v].lazy!=-1) downupdate(v);
//    
//    int mid=(tree[v].l+tree[v].r)/2;
//    if(a<=mid) changeadd_interval(v*2,a,b,y);
//    if(b>mid) changeadd_interval(v*2+1,a,b,y);
//    
//    tree[v].w=tree[v*2].w+tree[v*2+1].w;
//}

void changeupdate_interval(int v,int a,int b,int y)//区间改值,[a,b]内所有数同时修改为y 
{
    if(tree[v].l>=a&&tree[v].r<=b)
    {
        tree[v].w=(tree[v].r-tree[v].l+1)*y;
        tree[v].lazy=y;
        return;
    }
    //if(tree[v].lazy!=0) downadd(v);
    if(tree[v].lazy!=-1) downupdate(v);
    
    int mid=(tree[v].l+tree[v].r)/2;
    if(a<=mid) changeupdate_interval(v*2,a,b,y);
    if(b>mid) changeupdate_interval(v*2+1,a,b,y);
    
    tree[v].w=tree[v*2].w+tree[v*2+1].w;
}

int main()
{
	int t,n,m,tt=1;
	scanf("%d",&t);
	while(t--)
	{
		//memset(tree,0,sizeof(tree));
		memset(tree,-1,sizeof(tree));
		scanf("%d",&n);
		build(1,1,n);
		scanf("%d",&m);
		for(int i=1;i<=m;i++)
		{
			int a,b,y;
			scanf("%d%d%d",&a,&b,&y);
			changeupdate_interval(1,a,b,y);
		}
		printf("Case %d: The total value of the hook is ",tt++);
		printf("%d.\n",tree[1].w);
	}
    return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值