hdu 1698_1

来源:互联网 发布:js 数组里的对象去重 编辑:程序博客网 时间:2024/04/29 20:54

ProblemDescription

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

NowPudge wants to do some operations on the hook.
Let us number the consecutive metallic sticks ofthe hook from 1 to N. For each operation, Pudge can change the consecutivemetallic sticks, numbered from X to Y, into cupreous sticks, silver sticks orgolden sticks.
The total value of the hook is calculated as thesum of values of N metallic sticks. More precisely, the value for each kind ofstick 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 hookafter performing the operations.
You may consider the original hook is made up ofcupreous sticks.

Input

The inputconsists of several test cases. The first line of the input is the number ofthe cases. There are no more than 10 cases.
For each case, the first line contains an integer N, 1<=N<=100,000, whichis the number of the sticks of Pudge’s meat hook and the second line containsan 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 toY into the metal kind Z, where Z=1 represents the cupreous kind, Z=2 representsthe silver kind and Z=3 represents the golden kind.

Output

For eachcase, print a number in a line representing the total value of the hook afterthe operations. Use the format in the example.

题目大意:

有N个小棒子组成一条长的链,刚开始都是铜的,每个小棒子价值为1,输入一个区间,再输入一个1或2或3,表示该区间的棒子变成了银的或者金的,求出整个链的价值。

代码如下:

#include<iostream>

using namespace std ;

struct Node

{

   int value ;

   int L, R ;

}tree[300000];

int BuildTree(int root, int L, int R)

{

   tree[root].L = L ;

   tree[root].R = R ;

   if(L == R)

    {

       return tree[root].value = 1 ;

    }

   int mid = (L+R) / 2 ;

   return tree[root].value = BuildTree(2*root, L, mid) +BuildTree(2*root+1, mid+1, R) ;

}

int Update(int root, int L, int R, int v)

{

   if(tree[root].L == tree[root].R)

       return tree[root].value = v ;

   int mid = (tree[root].L + tree[root].R) / 2 ;

   if(L > mid)

       return tree[root].value = Update(2*root+1, L, R, v) + tree[2*root].value;

   else if(R <= mid)

       return tree[root].value = Update(2*root, L, R, v) + tree[2*root+1].value;

   else

       return tree[root].value = Update(2*root, L, mid, v) + Update(2*root+1,mid+1, R, v) ;

}

int main()

{

   int l, r, m, q, v, i, n ;

   scanf("%d\n", &m) ;

   for(i = 1; i <= m; i++)

    {

       scanf("%d", &n) ;

       BuildTree(1, 1, n) ;

       scanf("%d", &q) ;

       while(q--)

       {

           scanf("%d%d%d", &l, &r, &v) ;

           Update(1, l, r, v) ;

       }

       printf("Case %d: the total value of the the hook is %d\n", i,tree[1].value) ;

    }

   return 0 ;

}

运用线段树,采用单点更新的思想,每次区间的值的改变都转变成区间每个子区间的值得改变,一直更新值至树的叶子节点,这个想法比较直接,简单,但是,提供的数据只能过一部分,超时了,虽然没有A过,但是这个方法可以检验你对线段树的单点更新是否理解了。

有一种不用线段树就能A过的方法,代码如下:

#include<iostream>

using namespace std ;

int data[100000][3] ;

int main()

{

       intt, q, n, i, j, sum, k, v ;

       scanf("%d",&t) ;

       for(i= 1; i <= t; i++)

       {

              scanf("%d%d",&n, &q) ;

              for(j= 1; j <= q; j++)

                     scanf("%d%d%d",&data[j][0], &data[j][1], &data[j][2]) ;

              sum= 0 ;

              for(k= 1; k <= n; k++)

              {

                     v= 1 ;

                     for(j= q; j >= 1; j--)

                            if(data[j][0]<= k && k <= data[j][1])

                            {

                                   v= data[j][2] ;

                                   break;

                            }

                     sum+= v ;

              }

              printf("Case%d: The total value of the hook is %d.\n",i,sum) ;

       }

       return0 ;

}

既然输入的区间一直都是从小到大输入,那么我们先假设整个区间都是铜质的1,将区间价值改变的区间先存起来,整个区间倒着遍历,一旦某个点所在区间材质改变,就将价值v的值改变,最后也能得出整个区间的价值,而且用时非常少。

0 0
原创粉丝点击