Just a Hook

来源:互联网 发布:电脑视频文件恢复软件 编辑:程序博客网 时间:2024/06/15 20:38

Just a Hook - HDU 1698 - 线段树

题目:

  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

11021 5 25 9 3

Sample Output

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

  题意:第一行t代表样例组数,然后一个n代表节点数目,q代表update次数,最后是q行,每行a b c代表把区间[a,b]的每个数的权值都改为c,初始权值都为1,问最终的权值。

  思路:成段更新,还是线段树,用Lazy思想的话没有什么难点。WA了两次,一次是pushdown()函数写成了:

void pushdown(int u) {    if(node[ls]==node[rs]&&node[u]==node[ls]) {        return ;    }    else {        node[ls] = node[rs] = node[u];        node[u] = -1;    }}

  刚开始在执行效率的考虑下,觉得如果父节点和两个子节点的权都相同,就不用更改。可是后来发现,如果在最后一次操作中将某个节点的值改变的话,在query过程中这个节点的权会被再次更新成父节点的权。

  比如说现在节点B对应的区间[1,3]和节点C对应的区间[4,5]的权在某次update中被更新为3。而节点A对应的区间[1,5]此时对应的权为-1。显然,B、C是A的两个子树。而当我们在倒数第二个时刻,执行一次1 5 3,按照这个错误的代码流程来走的话,此时有A=B=C=3,然后在最后一次update操作中,执行4 5 1,那么此时,C=1,A=B=3。

  然后就会出现这样一种情况,在query的过程中,当询问到A节点也就是[1,5]这个区间的时候,发现A不是-1,就直接return了。B节点和C节点的权由于线段树的特性就直接被忽略了。所以在此我的一个小的总结就是:

  某个点在经历pushdown()操作之后一定要将其恢复成初始标记。

于是有:

void pushdown(int u) {    node[ls] = node[rs] = node[u];    node[u] = -1;}

  下面附上AC代码,自己的思路,比较好理解,效率也不是很低,看了一下VJudge里的提交记录,我是800ms,比我快的只有一个700ms的,好像效率不是很低。WA了一发,忘了在query之前将ans初始化为0。

////  main.cpp//  L////  Created by LucienShui on 2017/5/28.//  Copyright © 2017年 LucienShui. All rights reserved.//#include <iostream>#include <algorithm>#include <set>#include <string>#include <vector>#include <queue>#include <map>#include <iomanip>#include <cstdio>#include <cstring>#include <cmath>#include <cctype>#define memset(a,b) memset(a,b,sizeof(a))#define il inline#define ll long long#define ull unsigned long longusing namespace std;#define ls (u<<1)#define rs (u<<1|1)#define lson u<<1,l,mid#define rson u<<1|1,mid+1,rconst int maxn = 100000+7;int node[maxn<<2],ans;void pushdown(int u) {    node[ls] = node[rs] = node[u];    node[u] = -1;}void update(int u, int l, int r, int b, int e, int num) {    if(b <= l && r <= e) {        node[u] = num;        return ;    }    if(~node[u]) pushdown(u);    int mid = (l+r)>>1;    if(e<=mid) update(lson,b,e,num);    else if(b>mid) update(rson,b,e,num);    else {        update(lson,b,e,num);        update(rson,b,e,num);    }}void query(int u, int l, int r, int b, int e) {    if(b <= l && r <= e && ~node[u]) {        ans += node[u] * (r-l+1);        return ;    }    if(~node[u]) pushdown(u);    int mid = (l+r)>>1;    if(e<=mid) query(lson,b,e);    else if(mid<b) query(rson,b,e);    else {        query(lson,b,e);        query(rson,b,e);    }}int main (){#ifndef ONLINE_JUDGE    freopen("in.txt","r",stdin);#endif // ONLINE_JUDGE    int t,n,q,a,b,c,i=1;    cin >> t;    while(t--) {        scanf("%d%d",&n,&q);        ans = 0;        memset(node,-1);        node[1]=1;//将区间[1,n]的权置为1        while(q--) {            scanf("%d%d%d",&a,&b,&c);            update(1,1,n,a,b,c);        }        query(1,1,n,1,n);        printf("Case %d: The total value of the hook is %d.\n",i++,ans);    }    return 0;}
原创粉丝点击