HDU 1698 Just a Hook(區間修改,求累加和)


F - 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.
 


題目大意,一個區間,現在有金銀銅三個牌,現在要去一段區間內的進行統一發獎牌,發過 n 次後 求總共獎牌的總價值

所以就是 線段樹,區間修改,求累加和的…………。。。。。。。。。。。。。。。。。



線段樹單點修改和區間修改的區別;

對於點修改和區間修改區別其實並不大,在點修改的時候,我們是找到該點,然後對該點進行加減操作,然後再一次遞推修改其他的點,然後在區間修改中,有兩種修改情況,一種就是和點修改一樣的,找到點,修改點,遞推其他點,但是,這只是其中的一點修改,這種修改方式只佔用小部分。佔大部分的還是對整個區間進行修改,如果該結點所表示的區間在要更改的區間內,那麼就對該點直接修改,該節點加的值爲 該區間每個結點要加的值得總和



代碼的函數名稱的功能

●  PushUP(int rt)是把當前結點的信息更新到父結點

●  PushDown(int rt)是把當前結點的信息更新給兒子結點

●  build(int l,int r,int rt) 建立線段樹

●  rt表示當前子樹的根(root),也就是當前所在的結點


這道題和 poj 3468 比較相同,兩個代碼使用同一個模板就行,並且這道題求的結果是總共的和,所以,直接求 結點 1 的值,也就是 區間 1 - n 的值就行了,這篇的註釋我寫的少,附個 poj 3468 的鏈接,這個上面的註釋寫的比較多

POJ 3468 鏈接 : http://blog.csdn.net/xia842655187/article/details/51407226  點擊打開鏈接


附上代碼:

#include <cstdio>
#include <algorithm>
using namespace std;
#define LL long long
#define lson l , m , rt << 1
#define rson m + 1 , r , rt << 1 | 1
const int maxn = 111111;
int h , w , n;
int col[maxn<<2];
int sum[maxn<<2];
void PushUp(int rt) {
       sum[rt] = sum[rt<<1] + sum[rt<<1|1];
}
void PushDown(int rt,int m) {
       if (col[rt]) {
              col[rt<<1] = col[rt<<1|1] = col[rt];
              sum[rt<<1] = (m - (m >> 1)) * col[rt];
              sum[rt<<1|1] = (m >> 1) * col[rt];
              col[rt] = 0;
       }
}
void build(int l,int r,int rt) {
       col[rt] = 0;
       sum[rt] = 1;
       if (l == r) return ;
       int m = (l + r) >> 1;
       build(lson);
       build(rson);
       PushUp(rt);
}
void update(int L,int R,int c,int l,int r,int rt) {
       if (L <= l && r <= R) {
              col[rt] = c;
              sum[rt] = c * (r - l + 1);
              return ;
       }
       PushDown(rt , r - l + 1);
       int m = (l + r) >> 1;
       if (L <= m) update(L , R , c , lson);
       if (R > m) update(L , R , c , rson);
       PushUp(rt);
}

LL query(int L,int R,int l,int r,int rt) {
       if (L <= l && r <= R) {  //如果該點的區間在所求區間內,直接返回該值 
              return sum[rt];
       }
       //PushDown(rt , r - l + 1);  //根據該點的信息  遞推修改兒子節點的信息 
       int m = (l + r) >> 1;
       LL ret = 0;
       if (L <= m) ret += query(L , R , lson);       
       if (m < R) ret += query(L , R , rson);
       return ret;
}

int main() {
       int T , n , m;
       scanf("%d",&T);
       for (int cas = 1 ; cas <= T ; cas ++) {
              scanf("%d%d",&n,&m);
              build(1 , n , 1);
              while (m --) {
                     int a , b , c;
                     scanf("%d%d%d",&a,&b,&c);
                     update(a , b , c , 1 , n , 1);
              }
              printf("Case %d: The total value of the hook is %d.\n",cas , query(1,n,1,n,1));
       }
       return 0;
}




發佈了106 篇原創文章 · 獲贊 31 · 訪問量 9萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章