hdu 1698+poj 3468 (线段树 区间更新)

http://acm.hdu.edu.cn/showproblem.php?pid=1698

这个题意翻译起来有点猥琐啊,还是和谐一点吧

和涂颜色差不多,区间初始都为1,然后操作都是将x到y改为z,注意 是改为z,不是加或减,最后输出区间总值

也是线段树加lazy操作

 1 #include<cstdio>
 2 using namespace std;
 3 struct point {
 4     int l,r;
 5     int val,sum;
 6 };
 7 point tree[400007];
 8 void build(int i,int left,int right)
 9 {
10     tree[i].l=left,tree[i].r=right;
11     tree[i].val=0;
12     if (left==right) {tree[i].sum=1;return;}
13     int mid=(left+right)/2;
14     build(i*2,left,mid);
15     build(i*2+1,mid+1,right);
16     tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
17 }
18 int update(int i,int left,int right,int val)
19 {
20     if (right==tree[i].r&&left==tree[i].l)
21     {
22         tree[i].val=val;
23         return tree[i].sum=(right-left+1)*val;
24     }
25     if (tree[i].val)
26     {
27         tree[i*2].val=tree[i*2+1].val=tree[i].val;
28         tree[i*2].sum=(tree[i*2].r-tree[i*2].l+1)*tree[i].val;
29         tree[i*2+1].sum=(tree[i*2+1].r-tree[i*2+1].l+1)*tree[i].val;
30         tree[i].val=0;
31     }
32     int mid=(tree[i].r+tree[i].l)/2;
33     if (left>mid) return tree[i].sum=update(i*2+1,left,right,val)+tree[i*2].sum;
34     else if (right<=mid) return tree[i].sum=update(i*2,left,right,val)+tree[i*2+1].sum;
35     else  return tree[i].sum=update(i*2+1,mid+1,right,val)+update(i*2,left,mid,val);
36 }
37 int main()
38 {
39     int t,n,m,x,y,z,sum;
40     while (~scanf("%d",&t))
41     {
42         sum=1;
43         while (t--)
44         {
45             scanf("%d %d",&n,&m);
46             build(1,1,n);
47             while (m--)
48             {
49                 scanf("%d %d %d",&x,&y,&z);
50                 update(1,x,y,z);
51             }
52             printf("Case %d: The total value of the hook is %d.\n",sum++,tree[1].sum);
53         }
54     }
55     return 0;
56 }

http://poj.org/problem?id=3468

这个和上面一样,只是变成了加上z,所以就变成了在原有的值上再加,+=,改改就行,数值比较大,应该用int64

 1 #include<cstdio>
 2 #define ll __int64
 3 using namespace std;
 4 struct point {
 5     ll l,r;
 6     ll val,sum;
 7 };
 8 point tree[400007];
 9 ll num[100007];
10 void build(ll i,ll left,ll right)
11 {
12     tree[i].l=left,tree[i].r=right;
13     tree[i].val=0;
14     if (left==right) {tree[i].sum=num[left];return;}
15     int mid=(left+right)/2;
16     build(i*2,left,mid);
17     build(i*2+1,mid+1,right);
18     tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;
19 }
20 ll update(ll i,ll left,ll right,ll val)
21 {
22     if (right==tree[i].r&&left==tree[i].l)
23     {
24         tree[i].val+=val;
25         return tree[i].sum+=(right-left+1)*val;
26     }
27     if (tree[i].val)
28     {
29         tree[i*2].val+=tree[i].val;
30         tree[i*2+1].val+=tree[i].val;
31         tree[i*2].sum+=(tree[i*2].r-tree[i*2].l+1)*tree[i].val;
32         tree[i*2+1].sum+=(tree[i*2+1].r-tree[i*2+1].l+1)*tree[i].val;
33         tree[i].val=0;
34     }
35     int mid=(tree[i].r+tree[i].l)/2;
36     if (left>mid) return tree[i].sum=update(i*2+1,left,right,val)+tree[i*2].sum;
37     else if (right<=mid) return tree[i].sum=update(i*2,left,right,val)+tree[i*2+1].sum;
38     else  return tree[i].sum=update(i*2+1,mid+1,right,val)+update(i*2,left,mid,val);
39 }
40 ll find(ll i,ll left,ll right)
41 {
42     if (left>tree[i].r&&right<tree[i].l) return 0;
43     if (tree[i].l==left&&tree[i].r==right) return tree[i].sum;
44     if (tree[i].val)
45     {
46         tree[i*2].val+=tree[i].val;
47         tree[i*2+1].val+=tree[i].val;
48         tree[i*2].sum+=(tree[i*2].r-tree[i*2].l+1)*tree[i].val;
49         tree[i*2+1].sum+=(tree[i*2+1].r-tree[i*2+1].l+1)*tree[i].val;
50         tree[i].val=0;
51     }
52     ll mid=(tree[i].r+tree[i].l)/2;
53     if (left>mid) return find(i*2+1,left,right);
54     else if (right<=mid) return find(i*2,left,right);
55     else return find(i*2,left,mid)+find(i*2+1,mid+1,right);
56 }
57 int main()
58 {
59     ll n,m,i,z,x,y;
60     char op;
61     while (~scanf("%I64d %I64d",&n,&m))
62     {
63        for (i=1;i<=n;i++)
64           scanf("%I64d",&num[i]);
65        build(1,1,n);
66        while (m--)
67        {
68            scanf(" %c",&op);
69            if (op==‘C‘)
70            {
71                scanf("%I64d %I64d %I64d",&x,&y,&z);
72                update(1,x,y,z);
73            }
74            else
75            {
76                scanf("%I64d %I64d",&x,&y);
77                printf("%I64d\n",find(1,x,y));
78            }
79        }
80     }
81     return 0;
82 }
时间: 2024-09-28 04:17:34

hdu 1698+poj 3468 (线段树 区间更新)的相关文章

POJ 3468 线段树区间求和

线段树区间求和树节点不能只存和,只存和,会导致每次加数的时候都要更新到叶子节点,速度太慢(O(nlogn)).所以我们要存两个量,一个是原来的和nSum,一个是累加的增量Inc. 在增加时,如果要加的区间正好覆盖一个节点,则增加其节点的Inc值,不再往下走,否则要更新nSum(加上本次增量),再将增量往下传,这样更新的复杂度就是O(log(n)). 在查询时,如果待查区间不是正好覆盖一个节点,就将节点的Inc往下带,然后将Inc清0,接下来再往下查询. Inc往下带的过程也是区间分解的过程,复杂

HDU 3577 Fast Arrangement (线段树区间更新)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3577 题意不好理解,给你数字k表示这里车最多同时坐k个人,然后有q个询问,每个询问是每个人的上车和下车时间,每个人按次序上车,问哪些人能上车输出他们的序号. 这题用线段树的成段更新,把每个人的上下车时间看做一个线段,每次上车就把这个区间都加1,但是上车的前提是这个区间上的最大值不超过k.有个坑点就是一个人上下车的时间是左闭右开区间,可以想到要是一个人下车,另一个人上车,这个情况下这个点的大小还是不变

HDU 4902 Nice boat --线段树(区间更新)

题意:给一个数字序列,第一类操作是将[l,r]内的数全赋为x ,第二类操作是将[l,r]中大于x的数赋为该数与x的gcd,若干操作后输出整个序列. 解法: 本题线段树要维护的最重要的东西就是一个区间内所有数是否相等的标记.只维护这个东西都可以做出来. 我当时想歪了,想到维护Max[rt]表示该段的最大值,最大值如果<=x的话就不用更新了,但是好像加了这个“优化”跑的更慢了. 我想大概是因为如果两个子树最大值或者整个两个子树的数不完全相等的话,根本不能直接下传这个值或者下传gcd,因为你不知道要更

POJ 3468 (线段树 区间增减) A Simple Problem with Integers

这题WA了好久,一直以为是lld和I64d的问题,后来发现是自己的pushdown函数写错了,说到底还是因为自己对线段树理解得不好. 因为是懒惰标记,所以只有在区间分开的时候才会将标记往下传递.更新和查询都要pushdown. 1 #include <cstdio> 2 3 typedef long long LL; 4 5 const int maxn = 100000 + 10; 6 7 int n, m, qL, qR, v; 8 LL sum[maxn << 2], add

HDU 1540 POJ 2892 线段树区间合并

给出N个点,M次操作,N个点开始在一条线上链式相连 D操作  把某点删除掉 Q操作  询问某点一共可以连接多少个点 R操作  把上一次删除的点还原 线段树处理区间合并 分别记录每个区间的左端连续最长和右端连续最长 #include "stdio.h" #include "string.h" struct node { int l,r,lx,rx,x; }data[200010]; int mark[50100]; int Max(int a,int b) { if

hdu 3397 Sequence operation 线段树 区间更新 区间合并

题意: 5种操作,所有数字都为0或1 0 a b:将[a,b]置0 1 a b:将[a,b]置1 2 a b:[a,b]中的0和1互换 3 a b:查询[a,b]中的1的数量 4 a b:查询[a,b]中的最长连续1串的长度 这题看题目就很裸,综合了区间更新,区间合并 我一开始把更新操作全放一个变量,但是在push_down的时候很麻烦,情况很多,容易漏,后来改成下面的 更新的操作可以分为两类,一个是置值(stv),一个是互换(swp).如果stv!=-1,则更新儿子节点的stv,并将儿子的sw

POJ - 3468 线段树区间修改,区间求和

由于是区间求和,因此我们在更新某个节点的时候,需要往上更新节点信息,也就有了tree[root].val=tree[L(root)].val+tree[R(root)].val; 但是我们为了把懒标记打上,当节点表示的区间是完全被询问区间包含,那么这个区间的信息都是有用的,因此我们其实只需要把这个节点更新,并打上懒标记即可.如果以后update 或者 query 需要跑到下面,直接往下pushdown即可. pushdown的时候,由于当前层的信息已经更新,我们需要把信息往下推,并把子节点的信息

POJ 3225 (线段树 区间更新) Help with Intervals

这道题搞了好久,其实坑点挺多.. 网上找了许多题解,发现思路其实都差不多,所以就不在重复了. 推荐一篇比较好的题解,请戳这. 另外,如果因为可能要更新多次,但最终查询只需要一次,所以没有写pushup函数,仅有一个pushdown. 1 #include <cstdio> 2 3 const int maxn = 131072; 4 //const int maxn = 10; 5 int qL, qR, op; 6 int setv[maxn << 2], xorv[maxn &

A Simple Problem with Integers POJ - 3468 线段树区间修改+区间查询

//add,懒标记,给以当前节点为根的子树中的每一个点加上add(不包含根节点) // #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; typedef long long LL; const int N = 100010; int n, m; int w[N]; struct Node { int l, r;