luogu1438无聊的数列(区间加等差数列,求一个数的和)
QAQ一道线段树好题
题目大意:
给定一个有n个数的数列,共m种操作,有两种操作
\(1\ l\ r\ k\ d\)表示将\(a[l]\)~\(a[r]\)的数加一个以k为首相,d为公差
\(2\ x\)表示求\(a[x]\)是多少
QwQ又是一道不会的题
暴力修改肯定会T飞
如果可以用线段树进行区间修改呢??
我们考虑,对于一段区间\([l,r]\),我们只需要记录它的区间的首相和公差,就能将这个标记下传了
QwQ哇,那可以只使用这个线段树进行一个标记下传了(所以没有up函数)
这里展示一下pushdown的部分
\(f[root].d\)表示公差,\(f[root].first\)表示首相
void pushdown(int root,int l,int r)
{
if (f[root].d || f[root].first)
{
int mid = (l+r) >> 1;
f[2*root].d+=f[root].d;
f[2*root+1].d+=f[root].d;
f[2*root].first+=f[root].first;
f[2*root+1].first+=(f[root].first+(mid-l+1)*f[root].d);
f[root].d=f[root].first=0;
}
}
因为,等差数列相加依然是等差数列,所以对于公差和首相,可以直接加
对一个区间的话\([l,r]\),\([l,mid]\)这部分可以直接进行加法,而对于\([mid+1,r]\)稍微操作一下,修改首相即可
求和什么的,也比较简单
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<map>
#include<vector>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)) {if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)) {x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 100010;
struct Node{
int d,first;
};
Node f[4*maxn];
Node add[4*maxn];
int a[4*maxn];
int n,m;
void pushdown(int root,int l,int r)
{
if (f[root].d || f[root].first)
{
int mid = (l+r) >> 1;
f[2*root].d+=f[root].d;
f[2*root+1].d+=f[root].d;
f[2*root].first+=f[root].first;
f[2*root+1].first+=(f[root].first+(mid-l+1)*f[root].d);
f[root].d=f[root].first=0;
}
}
void update(int root,int l,int r,int x,int y,int first,int d)
{
if (x<=l && r<=y){
f[root].d+=d;
f[root].first+=(l-x)*d+first;
return ;
}
pushdown(root,l,r);
int mid = (l+r) >> 1;
if (x<=mid) update(2*root,l,mid,x,y,first,d);
if (y>mid) update(2*root+1,mid+1,r,x,y,first,d);
}
int query(int root,int l,int r,int pos)
{
if (l==r)
{
return a[l]+f[root].first;
}
pushdown(root,l,r);
int mid = (l+r) >> 1;
if (pos<=mid) return query(2*root,l,mid,pos);
if (pos>mid) return query(2*root+1,mid+1,r,pos);
}
int main()
{
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++) a[i]=read();
for (int i=1;i<=m;i++)
{
int opt;
opt=read();
if (opt==1)
{
int l,r,k,d;
l=read(),r=read(),k=read(),d=read();
update(1,1,n,l,r,k,d);
}
else
{
int x=read();
printf("%d\n",query(1,1,n,x));.
}
}
return 0;
}
luogu1438无聊的数列(区间加等差数列,求一个数的和)的更多相关文章
- [cdoj 1344]树状数组区间加等差数列
题目链接:http://acm.uestc.edu.cn/#/problem/show/1344 区间加等差数列本质上就是区间修改区间查询,本来想用线段树做,结果这个题就是卡空间和时间……不得已学了区 ...
- LUOGU1438无聊的数列
区间加等差数列单点查询 思路: 差分,通过树状数组修改,然后保存两个数组,一个存公差,一个存和 然后正常操作即可 在学校潦草写的很潦草啦 代码如下: #include<cstdio> #i ...
- Luogu1438 无聊的数列(单点查询)&&加强版(区间查询)
题目链接:戳我 线段树中差分和前缀和的应用 其实对于加上等差数列的操作我们可以分成这样三步-- update(1,1,n,l,l,k); if(r>l) update(1,1,n,l+1,r,d ...
- [luogu1438]无聊的数列
考虑令$b_{i}=a_{i+1}-a_{i}$,那么1操作相当于对L加上K,对(L,R]区间加上D,对R+1减去K+(R-L)*D,然后询问区间和即可 1 #include<bits/stdc ...
- [LuoguP1438]无聊的数列(差分+线段树/树状数组)
\(Link\) \(\color{red}{\mathcal{Description}}\) 给你一个数列,要求支持单点查询\(and\)区间加等差数列. \(\color{red}{\mathca ...
- LUOGU P1438 无聊的数列 (差分+线段树)
传送门 解题思路 区间加等差数列+单点询问,用差分+线段树解决,线段树里维护的就是差分数组,区间加等差数列相当于在差分序列中l位置处+首项的值,r+1位置处-末项的值,中间加公差的值,然后单点询问就相 ...
- [用CDQ分治解决区间加&区间求和]【习作】
[前言] 作为一个什么数据结构都不会只会CDQ分治和分块的蒟蒻,面对区间加&区间求和这么难的问题,怎么可能会写线段树呢 于是,用CDQ分治解决区间加&区间求和这篇习作应运而生 [Par ...
- LOJ6283 数列分块入门 7 (分块 区间加/乘)题解
题意:区间加,区间乘,单点询问 思路:假设一个点为a,那么他可以表示为m * a + sum,所以区间加就变为m * a + sum + sum2,区间乘变为m * m2 * a + sum * m2 ...
- P1438 无聊的数列 (差分+线段树)
题目 P1438 无聊的数列 解析: 先考虑修改,用差分的基本思想,左端点加上首项\(k\),修改区间\((l,r]\)内每个数的差分数组都加上公差\(d\),最后的\(r+1\)再减去\(k+(r- ...
随机推荐
- HTML5存储 ——Web Storage(localStorage 和 sessionStorage)
一.localStorage对象临时储存API 方法: 1.localStorage.setItem(key,value)---设置存储内容 2.localStorage.getItem(key)-- ...
- mybaits源码分析--日志模块(四)
一.日志模块 首先日志在我们开发过程中占据了一个非常重要的地位,是开发和运维管理之间的桥梁,在Java中的日志框架也非常多,Log4j,Log4j2,Apache Commons Log,java.u ...
- Spring笔记(3)
一.JDBC Template基本使用 1.开发步骤 1.1直接使用template 导入spring-jdbc和spring-tx坐标 <!-- JDBC--> <dependen ...
- JDK方法区、元空间区别 & String.intern相关面试题
一.方法区.永久代.元空间 1.方法区.永久代 方法区也是各个线程共享的内存区域,它用于存储已经被虚拟机加载的类信息.常量.静态变量.即时编译器编译后的代码等数据.方法区域又被称为"永久代& ...
- Selenium系列(十七) - Web UI 自动化基础实战(4)
如果你还想从头学起Selenium,可以看看这个系列的文章哦! https://www.cnblogs.com/poloyy/category/1680176.html 其次,如果你不懂前端基础知识, ...
- 手工添加数据到Chart
private void button1_Click(object sender, EventArgs e) { //清除Series chart1.Series.Clear(); Random ra ...
- Centos 6.8 系统下安装RabbitMQ方法
一,安装 RabbitMQ 首先要先安装 erlang 1,到erlang官网下载 OTP 19.0 Source File 2,解压 tar zvxf otp_src_19.0.tar.gz 3,c ...
- 【优化技术专题】「温故而知新」基于Quartz系列的任务调度框架的动态化任务实现分析
不提XXLJOB或者其他的调度框架,就看我接触的第一个任务调度框架Quartz(温故而知新) Quartz的动态暂停 恢复 修改和删除任务 实现动态添加定时任务,先来看一下我们初步要实现的目标效果图, ...
- 图论---DFS
图论---DFS 1. 图的遍历 在理解DFS算法之前,我们首先需要对什么是遍历进行了解,遍历的概念就是:从某一个点出发(一般是首或尾),依次将数据结构中的每一个数据访问且只访问一遍. 2. DFS简 ...
- 每日学习——C++习题
1.题目要求:求圆的面积,数据成员为半径r,定义为私有成员,要求用成员函数实现在键盘上输入圆半径,计算圆面积.输出圆面积三个功能,要求三个成员函数在类内声明,在类外定义 //定义类 class Cir ...