牛客练习赛28 - B

传送门

题目

qn姐姐最好了~

​ qn姐姐给你了一个长度为n的序列还有m次操作让你玩,

​ 1 l r 询问区间[l,r]内的元素和

​ 2 l r 询问区间[l,r]内的

元素的平方

​ 3 l r x 将区间[l,r]内的每一个元素都乘上x

​ 4 l r x 将区间[l,r]内的每一个元素都加上x

输入描述:

第一行两个数n,m

接下来一行n个数表示初始序列

就下来m行每行第一个数为操作方法opt,

若opt=1或者opt=2,则之后跟着两个数为l,r

若opt=3或者opt=4,则之后跟着三个数为l,r,x

操作意思为题目描述里说的

输出描述:

对于每一个操作1,2,输出一行表示答案

输入

复制

5 6
1 2 3 4 5
1 1 5
2 1 5
3 1 2 1
4 1 3 2
1 1 4
2 2 3

输出

复制

15
55
16
41

备注:

对于100%的数据 n=10000,m=200000 (注意是等于号)

保证所有询问的答案在long long 范围内

虽然这道题暴力能卡过去,真的是卡过去的,什么乱七八糟的宏定义、全局变量都要删了。。。


线段树做法:主要是处理x[i] * x[i]的前 n 项和,这里sum[][0]表示前区间和,sum[][1]表示区间内的元素平方和。

这里x = mul * x + add;下面是做各种操作后sum及懒惰标记的变化

乘法 * num:

mul[rt] = mul[rt] * num

add[rt] = add[rt] * num (如果add = 0,那么add * num = 0,如果add = a, 那么 x = (mul * x + a) * num,即 x = mul * num * x + a * num,按照x = mul * x + add的格式)

sum[][0] = sum[][0] * num

sum[][1] = sum[][1] * num * num

加法 + num:

add[rt] += num

sum[][1] += 2 * sum[][0] * num + (r - l + 1) * num * num

这里的sum[][0]是还没改变的,即这里先处理sum[][1],下面再处理sum[][0]。先来看单个元素的变化,(x + num) * (x + num) = x * x + 2 * num * x + num * num, 然后多个这样的式子相加,即可得上式,也可以解释为什么先处理sum[][1]

sum[][0] += (r - l + 1) * num

最后要记得long long,查询和更新都要下推标记,mul[]要初始化

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <cmath>
#include <queue>
#include <iomanip>
#include <stack>
#include <algorithm>
#include <vector>
#include <functional> using namespace std; typedef long long LL;
#define Fil(Array, len, num) fill(Array, Array + len, num)
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
const double PI = 3.1415926;
const double E = 2.1718281828;
const int MAXN = 10005;
const int INF = 0x3f3f3f3f;
const int MOD = 1e9 + 7; LL sum[MAXN << 2][3], add[MAXN << 2], mul[MAXN << 2];
void PushUp(LL rt)
{
sum[rt][0] = sum[rt << 1][0] + sum[rt << 1 | 1][0];
sum[rt][1] = sum[rt << 1][1] + sum[rt << 1 | 1][1];
} void PushDown(LL ln, LL rn, LL rt)
{
if(mul[rt] != 1)
{
mul[rt << 1] *= mul[rt], mul[rt << 1 | 1] *= mul[rt];
sum[rt << 1][1] *= mul[rt] * mul[rt], sum[rt << 1 | 1][1] *= mul[rt] * mul[rt];
sum[rt][0] *= mul[rt], sum[rt << 1 | 1][0] *= mul[rt];
mul[rt] = 1;
}
if(add[rt])
{
add[rt << 1] += add[rt], add[rt << 1 | 1] += add[rt];
sum[rt << 1][1] += 2 * sum[rt << 1][0] * add[rt] + ln * add[rt] * add[rt];
sum[rt << 1 | 1][1] += 2 * sum[rt << 1 | 1][0] * add[rt] + rn * add[rt] * add[rt];
sum[rt << 1][0] += ln * add[rt], sum[rt << 1 | 1][0] += rn * add[rt];
add[rt] = 0;
}
} void Build(LL l, LL r, LL rt)
{
add[rt] = 0, mul[rt] = 1;
if(l == r)
{
scanf("%lld", &sum[rt][0]);
sum[rt][1] = sum[rt][0] * sum[rt][0];
return ;
}
LL m = (l + r) >> 1;
Build(lson);
Build(rson);
PushUp(rt);
} void Updata_Add(LL L, LL R, LL num, LL l, LL r, LL rt)
{
if(L <= l && r <= R)
{
sum[rt][1] += 2 * sum[rt][0] * num + (r - l + 1) * num * num;
sum[rt][0] += (r - l + 1) * num;
add[rt] += num;
return ;
}
LL m = (l + r) >> 1;
PushDown(m - l + 1, r - m, rt);
if(L <= m)
Updata_Add(L, R, num, lson);
if(m < R)
Updata_Add(L, R, num, rson);
PushUp(rt);
} void Updata_mul(LL L, LL R, LL num, LL l, LL r, LL rt)
{
if(L <= l && r <= R)
{
sum[rt][0] *= num;
sum[rt][1] *= num * num;
mul[rt] *= num;
add[rt] *= num;
return ;
}
LL m = (l + r) >> 1;
PushDown(m - l + 1, r - m, rt);
if(L <= m)
Updata_mul(L, R, num, lson);
if(m < R)
Updata_mul(L, R, num, rson);
PushUp(rt);
} LL Query(LL L, LL R, LL l, LL r, LL rt, LL opt)
{
if(L <= l && r <= R)
{
if(opt == 1)
return sum[rt][0];
if(opt == 2)
return sum[rt][1];
}
LL ans = 0;
LL m = (l + r) >> 1;
PushDown(m - l + 1, r - m, rt);
if(L <= m)
ans += Query(L, R, lson, opt);
if(m < R)
ans += Query(L, R, rson, opt);
return ans;
} int main()
{
Fil(mul, (MAXN << 2), 1);
LL n, m;
scanf("%d%d", &n, &m);
Build(1, n, 1);
while(m--)
{
LL opt, l, r, x;
scanf("%d%d%d", &opt, &l, &r);
if(opt == 1 || opt == 2)
printf("%lld\n", Query(l, r, 1, n, 1, opt));
else if(opt == 3)
{
scanf("%lld", &x);
Updata_mul(l, r, x, 1, n, 1);
}
else
{
scanf("%lld", &x);
Updata_Add(l, r, x, 1, n, 1);
}
}
return 0;
}

牛客练习赛28-B(线段树,区间更新)的更多相关文章

  1. hdu 3966(树链剖分+线段树区间更新)

    传送门:Problem 3966 https://www.cnblogs.com/violet-acmer/p/9711441.html 学习资料: [1]线段树区间更新:https://blog.c ...

  2. hdu 1698 线段树 区间更新 区间求和

    Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  3. HDU3577 线段树(区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3577 ,普通的线段树区间更新题目,较简单. 相当于一个区间覆盖问题,有一点要注意的就是叶子节点是一个长 ...

  4. HDU 1556 Color the ball(线段树区间更新)

    Color the ball 我真的该认真的复习一下以前没懂的知识了,今天看了一下线段树,以前只会用模板,现在看懂了之后,发现还有这么多巧妙的地方,好厉害啊 所以就应该尽量搞懂 弄明白每个知识点 [题 ...

  5. hihoCoder 1080 : 更为复杂的买卖房屋姿势 线段树区间更新

    #1080 : 更为复杂的买卖房屋姿势 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 小Hi和小Ho都是游戏迷,“模拟都市”是他们非常喜欢的一个游戏,在这个游戏里面他们 ...

  6. HDU 5023 A Corrupt Mayor's Performance Art(线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5023 解题报告:一面墙长度为n,有N个单元,每个单元编号从1到n,墙的初始的颜色是2,一共有30种颜色 ...

  7. HDU 4902 Nice boat 2014杭电多校训练赛第四场F题(线段树区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4902 解题报告:输入一个序列,然后有q次操作,操作有两种,第一种是把区间 (l,r) 变成x,第二种是 ...

  8. HDU 1698 线段树 区间更新求和

    一开始这条链子全都是1 #include<stdio.h> #include<string.h> #include<algorithm> #include<m ...

  9. POJ-2528 Mayor's posters (线段树区间更新+离散化)

    题目分析:线段树区间更新+离散化 代码如下: # include<iostream> # include<cstdio> # include<queue> # in ...

随机推荐

  1. Greeplum 系列(四) 数据的装载与卸裁

    Greeplum 系列(四) 数据的装载与卸裁 装载数据有以下种方法: insert copy 外部表 gpload 下面以 member_delta 表为例分别介绍这四种方法. create tab ...

  2. MapReduce的初次尝试

    ====前提: 搭建好集群环境(zookeeper.hadoop.hbase). 搭建方法这里就不进行介绍了,网上有很多博客在介绍这些. ====简单需求: WordCount单词计数,号称Hadoo ...

  3. HUST软工1501-1503班第4周作业成绩公布

    说明 本次公布的成绩为第四周作业的结果: 第4周小组作业:WordCount优化 如果同学对作业结果存在异议,可以: 在毕博平台讨论区的第4周在线答疑区发帖申诉. 或直接在博客园本帖中进行评论进行申诉 ...

  4. CTE递归限制次数

    CTE可以用来取递归,网上资料很多,这里就不再叙述了,今天遇到的需求是要限制只取2级,然后加了个临时的lev with tree as(select [CustomerID],[CustomerNam ...

  5. 浏览器透明设置例子,qt5.6才支持

    用simpleBrowser例子的基础上,在BrowserWindow构造函数修改如下 BrowserWindow::BrowserWindow(QWidget *parent, Qt::Window ...

  6. SpringMVC的问题No mapping found for HTTP request with URI

    做了一个屏蔽进数据库的操作: Applicaition.xml配置: <?xml version="1.0" encoding="UTF-8"?> ...

  7. Ubuntu 将应用程序 固定到快快速启动栏(以Sublime为例)

    因为Sublime Text并不是需要安装,所以缺少Ubuntu桌面运行的一些基本配置,比如不能将它加入桌面侧边的启动器. 而Ubuntu上也没有快捷方式的说法,而通过软件中心安装的软件就有图标,并能 ...

  8. 多线程“尚未调用coinitialize” 报错

    关于多线程中创建使用TADOConnect.TADODataSet等Com组件时,必须先初始化Com 在多线程启用执行前 CoInitialize(nil); 在多线程启用执行后 CoUninitia ...

  9. scvmm2008 错误 2941 0x80072efe

    该错误是由于vmm和主机之间的证书不匹配所导致的. 1. 运行mmc,文件=>添加管理单元=>添加证书=>计算机账户=>本地计算机. 2. 在下图各个目录证书下删除和vmm关联 ...

  10. 解决Struts2拦截器的对于参数传递无效问题

    今天做项目时,使用拦截器对用户权限检查.拦截器本身没有问题,可是实现权限拦截,但是传递的参数全部都无效了.搞了很久,由于对拦截器的内部机制不是特别熟悉,所以重新研读了一下Struts2的拦截器.找到了 ...