牛客练习赛28B (经典)【线段树】
<题目链接>
输入描述:
第一行两个数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 范围内 解题分析:
本题主要的难点在于,对区间进行加或者乘上一个数后,如何快速的维护每个节点的sum 和pfh(区间所有数平方和) 值,如果仅仅是对区间的每个节点进行暴力单点更新的话,毫无疑问会超时。所以我们必须对区间整体修改,而且我们要想到,在区间的维度上,是可以对该区间的每个数平方和进行修改的,它并不像开根号一样,必须要下放到每个叶子节点,对具体的数进行开根。区间修改pfh值时,只需要利用平方和展开式,就能很容易的对区间平方和进行修改。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; #define Lson rt<<1,l,mid
#define Rson rt<<1|1,mid+1,r
typedef long long ll;
const int M = 1e4+;
ll n,m,arr[M];
struct Tree{
ll sum,pfh,add,mul;
}tr[M<<];
void Pushup(ll rt){
tr[rt].sum=tr[rt<<].sum+tr[rt<<|].sum;
tr[rt].pfh=tr[rt<<].pfh+tr[rt<<|].pfh; //pfh记录的是该区间所有元素的平方和
}
void Pushdown(ll rt,ll len){ //mul和add相当于两个lazy标记
if(tr[rt].mul!=){
ll tmp=tr[rt].mul;
tr[rt<<].sum*=tmp,tr[rt<<|].sum*=tmp;
tr[rt<<].pfh=tr[rt<<].pfh*tmp*tmp,tr[rt<<|].pfh=tr[rt<<|].pfh*tmp*tmp; //相当于对该区间的每个数都进行平方
tr[rt<<].mul*=tmp,tr[rt<<|].mul*=tmp; //这几个标记都要*mul
tr[rt<<].add*=tmp,tr[rt<<|].add*=tmp;
tr[rt].mul=;
}
if(tr[rt].add){
ll tmp=tr[rt].add;
tr[rt<<].pfh=tr[rt<<].pfh+*tmp*tr[rt<<].sum+tmp*tmp*(len-(len>>)); //注意这里,要将更新pfh的语句放在更新sum的语句之前
tr[rt<<|].pfh=tr[rt<<|].pfh+*tmp*tr[rt<<|].sum+tmp*tmp*(len>>);
tr[rt<<].sum+=tmp*(len-(len>>)),tr[rt<<|].sum+=tmp*(len>>);
tr[rt<<].add+=tmp,tr[rt<<|].add+=tmp;
tr[rt].add=;
}
}
void build(ll rt,ll l,ll r){
tr[rt].add=,tr[rt].mul=;
if(l==r){
tr[rt].sum=arr[l],tr[rt].pfh=arr[l]*arr[l];
return;
}
ll mid=(l+r)>>;
build(Lson);
build(Rson);
Pushup(rt);
}
void update1(ll rt,ll l,ll r,ll L,ll R,ll c){
if(L<=l&&r<=R){
tr[rt].sum*=c,tr[rt].add*=c,tr[rt].mul*=c;
tr[rt].pfh*=tr[rt].pfh*c*c;
return;
}
Pushdown(rt,r-l+);
ll mid=(l+r)>>;
if(L<=mid)update1(Lson,L,R,c);
if(R>mid)update1(Rson,L,R,c);
Pushup(rt);
}
void update2(ll rt,ll l,ll r,ll L,ll R,ll c){
if(L<=l&&r<=R){
tr[rt].pfh=tr[rt].pfh+*c*tr[rt].sum+c*c*(r-l+); //注意这里,要将更新pfh的语句放在更新sum的语句之前
tr[rt].add+=c;
tr[rt].sum+=c*(r-l+);
return;
}
Pushdown(rt,r-l+);
ll mid=(l+r)>>;
if(L<=mid)update2(Lson,L,R,c);
if(R>mid)update2(Rson,L,R,c);
Pushup(rt);
}
ll query(ll rt,ll l,ll r,ll L,ll R,ll ty){
if(L<=l&&r<=R){
if(ty==)return tr[rt].sum;
else return tr[rt].pfh;
}
Pushdown(rt,r-l+);
ll mid=(l+r)>>;
ll ans=;
if(L<=mid)ans+=query(Lson,L,R,ty);
if(R>mid)ans+=query(Rson,L,R,ty);
return ans;
}
int main(){
scanf("%lld%lld",&n,&m);
for(int i=;i<=n;i++)scanf("%lld",&arr[i]);
build(,,n);
while(m--){
ll op,x,y,c;
scanf("%lld%lld%lld",&op,&x,&y);
if(op==||op==){
printf("%lld\n",query(,,n,x,y,op));
}
else{
scanf("%lld",&c);
if(op==)update1(,,n,x,y,c);
else update2(,,n,x,y,c);
}
}
return ;
}
2018-10-05
牛客练习赛28B (经典)【线段树】的更多相关文章
- 牛客练习赛28-B(线段树,区间更新)
牛客练习赛28 - B 传送门 题目 qn姐姐最好了~ qn姐姐给你了一个长度为n的序列还有m次操作让你玩, 1 l r 询问区间[l,r]内的元素和 2 l r 询问区间[l,r]内的 ...
- 牛客练习赛63 牛牛的树行棋 差分 树上博弈 sg函数
LINK:牛牛的树行棋 本来是不打算写题解的. 不过具体思考 还是有一段时间的. 看完题 一直想转换到阶梯NIM的模型上 转换失败. 考虑SG函数. 容易发现 SG函数\(sg_x=max{sg_{t ...
- 牛客练习赛52 B Galahad (树状数组)
题目链接:https://ac.nowcoder.com/acm/contest/1084/B 题意 5e5的区间,5e5个询求[l,r]区间内出现过的数的和 思路 1s时限,莫队显然会T 我们可以将 ...
- 牛客练习赛70 D.数树 (模拟,STL)
题意:每次有\(3\)中操作,对两个点连条边,删去某条边,或者问当前大小不为\(1\)的树的数量.连重边或者删去一条不存在的边,这样的白痴操作可以无视qwq. 题解:水题,用map存一下pair然后分 ...
- 牛客练习赛 29 E 位运算?位运算!(线段树)
题目链接 牛客练习赛29E 对$20$位分别建立线段树.首先$1$和$2$可以合起来搞(左移右移其实是等效的) 用个lazy标记下.转移的时候加个中间变量. $3$和$4$其实就是区间$01$覆盖操 ...
- 牛客练习赛11 假的字符串 (Trie树+拓扑找环)
牛客练习赛11 假的字符串 (Trie树+拓扑找环) 链接:https://ac.nowcoder.com/acm/problem/15049 来源:牛客网 给定n个字符串,互不相等,你可以任意指定字 ...
- 【并查集缩点+tarjan无向图求桥】Where are you @牛客练习赛32 D
目录 [并查集缩点+tarjan无向图求桥]Where are you @牛客练习赛32 D PROBLEM SOLUTION CODE [并查集缩点+tarjan无向图求桥]Where are yo ...
- ZOJ - 1610 经典线段树染色问题
这个是一个经典线段树染色问题,不过题目给的是左右左右坐标,即[0,3]包含0-1这一段 1-2这一段 2-3这一段,和传统的染色不太一样,不过其实也不用太着急. 我们把左边的坐标+1,即可,那么[0, ...
- 牛客练习赛31 B 赞迪卡之声妮莎与奥札奇 逻辑,博弈 B
牛客练习赛31 B 赞迪卡之声妮莎与奥札奇 https://ac.nowcoder.com/acm/contest/218/B 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 2621 ...
随机推荐
- Confluence 6 找到你的支持识别代码(SEN)
你可以在下面 3 个地方找到你的 SEN 代码: 在 Confluence 中,进入 > 基本配置(General Configuration) > 许可证详细(License Deta ...
- android中调用c++文件并转为so
1.新建项目,不选include support c++ 报错:Error:Failed to open zip file.Gradle's dependency cache may be corru ...
- gnuradio 初次使用
参考链接: 入门 http://www.cnblogs.com/moon1992/p/5739027.html 创建模块 http://www.cnblogs.com/moon1992/p/54246 ...
- Netty多人聊天室
在简单聊天室的代码中修改ChatServerHandler类,就可以模拟多人聊天的功能 package com.cppdy.server; import io.netty.channel.Channe ...
- mysql通配符使用
mysql通配符使用: w3cchool 在mysql查询中,经常会用到通配符,而且mysql的通配符和pgsql是有所不同的,甚至mysql中还可以使用正则表达式.本文就为大家带来mysql查询中通 ...
- ubuntu18.04进不了桌面
ubuntu升级18.04进不了桌面 https://chengfeng.site/2018/05/02/ubuntu%E5%8D%87%E7%BA%A718-04%E8%B8%A9%E7%9A%84 ...
- CF508E
贪心题是很有趣的... 首先,本题为括号匹配问题,那么可以考虑进行栈模拟 然后,我们思考一下如何匹配:虽然题目中仅对右括号的位置提出了区域性要求,但可以发现,对能匹配上的栈顶括号立刻进行匹配一定是一种 ...
- 解决linux下svn update 产生Node remains in conflict的问题
提交一个文件 服务器上死活更新不了 是因为有冲突,解决办法:svn revert --depth=infinity /var/SvnProject/APITest 再次执行更新 进有改动的文件夹,更新 ...
- Jmeter 传值对比
${XXX}----------------------->在同一线程内可任务调用变量: vars.put(row,rowNum); ----------------------->var ...
- Update openssh7.9 on centos6
一.制作RPM安装包1)依赖安装yum install rpm-build gcc make wget openssl-devel krb5-devel pam-devel libX11-devel ...