线段树(成段更新) HDU 1698 Just a Hook

题目传送门

  1 /*
  2     线段树-成段更新:第一题!只要更新区间,输出总长度就行了
  3     虽然是超级裸题,但是用自己的风格写出来,还是很开心的:)
  4 */
  5 #include <cstdio>
  6 #include <algorithm>
  7 #include <cmath>
  8 #include <cstring>
  9 #include <string>
 10 #include <iostream>
 11 using namespace std;
 12
 13 #define lson l, mid, rt << 1
 14 #define rson mid + 1, r, rt << 1 | 1
 15
 16 const int MAXN = 1e5 + 10;
 17 const int INF = 0x3f3f3f3f;
 18 struct Node
 19 {
 20     int v, sum, add, mx, mn, len;
 21 }node[MAXN<<2];
 22
 23 void push_up(int rt)
 24 {
 25     node[rt].sum = node[rt<<1].sum + node[rt<<1|1].sum;
 26 }
 27
 28 void push_down(int rt, int c)
 29 {
 30     if (node[rt].add)
 31     {
 32         node[rt<<1].add = node[rt<<1|1].add = node[rt].add;
 33         node[rt<<1].sum = node[rt<<1].add * (c - (c >> 1));
 34         node[rt<<1|1].sum = node[rt<<1|1].add * (c >> 1);
 35         node[rt].add = 0;
 36     }
 37 }
 38
 39 void build(int l, int r, int rt)
 40 {
 41     node[rt].add = 0;
 42     if (l == r)    {node[rt].sum = 1;        return ;}
 43     int mid = (l + r) >> 1;
 44     build (lson);    build (rson);
 45
 46     push_up (rt);
 47 }
 48
 49 void updata(int ql, int qr, int c, int l, int r, int rt)
 50 {
 51     if (ql <= l && r <= qr)    {node[rt].sum = c * (r - l + 1);    node[rt].add = c;    return ;}
 52
 53     push_down (rt, r - l + 1);
 54
 55     int mid = (l + r) >> 1;
 56     if (ql <= mid)    updata (ql, qr, c, lson);
 57     if (qr > mid)    updata (ql, qr, c, rson);
 58
 59     push_up (rt);
 60 }
 61
 62 int query(int ql, int qr, int l, int r, int rt)
 63 {
 64     if (ql <= l && r <= qr)    {return node[rt].sum;}
 65
 66     push_down (rt, r - l + 1);
 67
 68     int mid = (l + r) >> 1;        int ans = 0;
 69     if (ql <= mid)    ans = query (ql, qr, lson);
 70     if (qr > mid)    ans = query (ql, qr, rson);
 71
 72     return ans;
 73 }
 74
 75 int main(void)        //HDU 1698 Just a Hook
 76 {
 77     //freopen ("HDOJ_1698.in", "r", stdin);
 78
 79     int t, cas = 0;
 80     scanf ("%d", &t);
 81     while (t--)
 82     {
 83         int n, q;
 84         scanf ("%d", &n);
 85         build (1, n, 1);
 86
 87         scanf ("%d", &q);
 88         while (q--)
 89         {
 90             int ql, qr, c;
 91             scanf ("%d%d%d", &ql, &qr, &c);
 92             updata (ql, qr, c, 1, n, 1);
 93         }
 94
 95         printf ("Case %d: The total value of the hook is %d.\n", ++cas, node[1].sum);
 96     }
 97
 98     return 0;
 99 }
100
101 /*
102 Case 1: The total value of the hook is 24.
103 */
时间: 2024-10-17 15:13:20

线段树(成段更新) HDU 1698 Just a Hook的相关文章

线段树成段更新 hdu 1698 Just a Hook

题意:给出n根金属棒,和操作数q,初始时每个金属棒价值都为1,每次操作可以把从x到y的金属棒更换材质,铜为1,银为2,金为3,最后统计所有的金属棒总价值是多少. 线段树成段更新,需要用到lazy标记,所谓lazy标记就是:更新一个区间的时候不更新到底,只更新到第一个满足更新范围的区间(即范围内的最大的区间),然后给节点加上lazy标记,以后需要更新到该节点的子节点的时候,就把lazy标记转移到子节点上,这样大大提升了效率. 代码:

HDU 1698 Just a Hook (线段树 成段更新 lazy-tag思想)

题目链接 题意: n个挂钩,q次询问,每个挂钩可能的值为1 2 3,  初始值为1,每次询问 把从x到Y区间内的值改变为z.求最后的总的值. 分析:用val记录这一个区间的值,val == -1表示这个区间值不统一,而且已经向下更新了, val != -1表示这个区间值统一, 更新某个区间的时候只需要把这个区间分为几个区间更新就行了, 也就是只更新到需要更新的区间,不用向下更新每一个一直到底了,在更新的过程中如果遇到之前没有向下更新的, 就需要向下更新了,因为这个区间的值已经不统一了. 其实这就

Codeforces Round #149 (Div. 2) E. XOR on Segment (线段树成段更新+二进制)

题目链接:http://codeforces.com/problemset/problem/242/E 给你n个数,m个操作,操作1是查询l到r之间的和,操作2是将l到r之间的每个数xor与x. 这题是线段树成段更新,但是不能直接更新,不然只能一个数一个数更新.这样只能把每个数存到一个数组中,长度大概是20吧,然后模拟二进制的位操作.仔细一点就行了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath>

POJ 2777 Count Color (线段树成段更新+二进制思维)

题目链接:http://poj.org/problem?id=2777 题意是有L个单位长的画板,T种颜色,O个操作.画板初始化为颜色1.操作C讲l到r单位之间的颜色变为c,操作P查询l到r单位之间的颜色有几种. 很明显的线段树成段更新,但是查询却不好弄.经过提醒,发现颜色的种类最多不超过30种,所以我们用二进制的思维解决这个问题,颜色1可以用二进制的1表示,同理,颜色2用二进制的10表示,3用100,....假设有一个区间有颜色2和颜色3,那么区间的值为二进制的110(十进制为6).那我们就把

POJ 2528 Mayor&#39;s posters (hash+线段树成段更新)

题意:有一面墙,被等分为1QW份,一份的宽度为一个单位宽度.现在往墙上贴N张海报,每张海报的宽度是任意的,但是必定是单位宽度的整数倍,且<=1QW.后贴的海报若与先贴的海报有交集,后贴的海报必定会全部或局部覆盖先贴的海报.现在给出每张海报所贴的位置(左端位置和右端位置),问张贴完N张海报后,还能看见多少张海报?(PS:看见一部分也算看到.) 思路:简单的成段更新,但是数据量是1千万,会MT,所以要区间压缩(离散化),保证覆盖的关系不变,离散化的时候有个易错的细节,poj数据水了,这个易错点引用h

POJ训练计划2777_Count Color(线段树/成段更新/区间染色)

解题报告 题意: 对线段染色,询问线段区间的颜色种数. 思路: 本来直接在线段树上染色,lz标记颜色.每次查询的话访问线段树,求出颜色种数.结果超时了,最坏的情况下,染色可以染到叶子节点. 换成存下区间的颜色种数,这样每次查询就不用找到叶子节点了,用按位或来处理颜色种数. #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace

Light OJ 1411 Rip Van Winkle`s Code 线段树成段更新

题目来源:Light OJ 1411 Rip Van Winkle`s Code 题意:3中操作 1种查询 求区间和 其中每次可以把一段区间从左到右加上1,2,3,...或者从右到左加上...3,2,1 或者把某个区间的数都置为v 思路:我是加了6个域 add是这段区间每个数都要加上add  add是这么来的 对与123456...这个等差数列 可能要分为2个区间 那么我就分成123和123 两个右边的等差数列每个数还应该加上3 所以右区间add加3 v是这个区间都要置为v 他的优先级最高 b是

poj 3468 A Simple Problem with Integers (线段树成段更新)

A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 77486   Accepted: 23862 Case Time Limit: 2000MS Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. One type of

poj 3468 A Simple Problem with Integers 【线段树-成段更新】

题目:poj 3468 A Simple Problem with Integers 题意:给出n个数,两种操作 1:l -- r 上的所有值加一个值val 2:求l---r 区间上的和 分析:线段树成段更新,成段求和 树中的每个点设两个变量sum 和 num ,分别保存区间 l--r 的和 和l---r 每个值要加的值 对于更新操作:对于要更新到的区间上面的区间,直接进行操作 加上 (r - l +1)* val .下面的区间标记num += val 对于求和操作,每次进行延迟更新,把num值