Tinamei
其实你不知道你不知道
Just a Hook
Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u

Description

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.
 
一hook由若干金属金银铜stick组成,在一个hook上进行若干操作(把金属stick替换其他类型,铜是1银是2金是3个价值,问最后操作之后总的value是多少
由于数据太多,我们用线段树处理,建树查询更新。

解题思路:

  线段树更新。因为数据范围的问题,每次更新到节点会TLE。用区间更新就会节省很多的时间,对每一个区间来讲,如果这个区间里面的棍子都是相同类型的,就用一个节点变量记录棍子类型,如果区间内棍子是不同类型,则将变量记录为-1。

#include<iostream>
#include<cstdio>

using namespace std;

#define N 100005

struct node
{
    int l, r, sum;
}tree[4*N];

void Build(int root, int l, int r)
{
    tree[root].l = l;
    tree[root].r = r;

    tree[root].sum = 1;  // 最开始sum都是1,即最开始都是铜金属

    if(l == r)
        return ;

    Build(2*root+1, l, (l+r)/2);
    Build(2*root+2, (l+r)/2+1, r);
}

void inset(int root, int l, int r, int c)
{
    if(tree[root].l == l && tree[root].r == r)
    {
        tree[root].sum = c;
        return ;
    }
    if(tree[root].sum != -1)  // 如果root这棵树上,左右两个子树上的金属状态一样,但是在这颗树上有要更新的数,所以这个树上的状态就不一样了,就把tree【root】置为-1,把该树的金属状态传下去
    {
        tree[root*2+1].sum = tree[root*2+2].sum = tree[root].sum;
        tree[root].sum = -1;
    }

    int mid = (tree[root].l+tree[root].r)/2;

    if(r <= mid)
        inset(2*root+1, l, r, c);
    else if(l > mid)
        inset(2*root+2, l, r, c);
    else
    {
        inset(2*root+1, l, mid, c);
        inset(2*root+2, mid+1, r, c);
    }
}

int query(int root, int l, int r)
{
    if(tree[root].sum != -1)  // 如果root这个树上的左右两个树上的金属状态一样就直接return树上的数的总和
        return tree[root].sum*(r-l+1);

    int mid = (tree[root].l+tree[root].r)/2;

    return query(2*root+1, l, mid)+query(2*root+2, mid+1, r);
}

int main()
{
    int t, q, n, a, b, c;

    scanf("%d", &t);

    for(int k = 1; k <= t; k++)
    {
        scanf("%d", &n);

        Build(0, 1, n);

        scanf("%d", &q);

        for(int i = 0; i < q; i++)
        {
            scanf("%d%d%d", &a, &b, &c);
            inset(0, a, b, c);
        }
        printf("Case %d: The total value of the hook is %d.\n", k, query(0, 1, n));
    }
    return 0;
}

http://www.cnblogs.com/alihenaixiao/p/4616575.html

posted on 2015-08-02 13:27  Tinamei  阅读(244)  评论(0编辑  收藏  举报