Luogu1438 无聊的数列(单点查询)&&加强版(区间查询)
题目链接:戳我
线段树中差分和前缀和的应用
其实对于加上等差数列的操作我们可以分成这样三步——
update(1,1,n,l,l,k);
if(r>l) update(1,1,n,l+1,r,d);
if(r!=n) update(1,1,n,r+1,r+1,-(r-l)*d-k);
然后查询的时候1到当前位置的和就是这个数的值啦!
代码如下:
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define MAXN 100010
using namespace std;
int n,m;
int a[MAXN];
struct Node{int l,r,sum,tag;}t[MAXN<<2];
inline int ls(int x){return x<<1;}
inline int rs(int x){return x<<1|1;}
inline void push_up(int x){t[x].sum=t[ls(x)].sum+t[rs(x)].sum;}
inline void solve(int x,int l,int r,int k)
{
t[x].tag+=k;
t[x].sum+=(r-l+1)*k;
}
inline void push_down(int x,int l,int r)
{
if(t[x].tag)
{
int mid=(l+r)>>1;
solve(ls(x),l,mid,t[x].tag);
solve(rs(x),mid+1,r,t[x].tag);
t[x].tag=0;
}
}
inline void update(int x,int l,int r,int ll,int rr,int k)
{
if(ll<=l&&r<=rr)
{
t[x].sum+=(r-l+1)*k;
t[x].tag+=k;
return;
}
int mid=(l+r)>>1;
push_down(x,l,r);
if(ll<=mid) update(ls(x),l,mid,ll,rr,k);
if(mid<rr) update(rs(x),mid+1,r,ll,rr,k);
push_up(x);
}
inline int query(int x,int l,int r,int ll,int rr)
{
int cur_ans=0;
if(ll<=l&&r<=rr) return t[x].sum;
int mid=(l+r)>>1;
push_down(x,l,r);
if(ll<=mid) cur_ans+=query(ls(x),l,mid,ll,rr);
if(mid<rr) cur_ans+=query(rs(x),mid+1,r,ll,rr);
return cur_ans;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=m;i++)
{
int op,l,r,k,d,p;
scanf("%d",&op);
if(op==1)
{
scanf("%d%d%d%d",&l,&r,&k,&d);
update(1,1,n,l,l,k);
if(r>l) update(1,1,n,l+1,r,d);
if(r!=n) update(1,1,n,r+1,r+1,-(r-l)*d-k);
}
else
{
scanf("%d",&p);
printf("%d\n",query(1,1,n,1,p)+a[p]);
}
}
return 0;
}
PS:(蒟蒻的一点小想法)
这道题让我们求的是单点查询。。。如果是区间查询呢?
这样我们就别用前缀和来表示这个数了,但是因为等差数列完全满足可加性,还是可以直接上线段树的啊!
下面是代码:(应该是没有什么问题,因为是在大佬的单点查询的代码基础上更改的)
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
#define MAX 1100000
#define lson (now<<1)
#define rson (now<<1|1)
struct Node
{
int s,lyk,lyd;
void put(int now,int l,int r,int K,int D)
{
int la=(r-l)*D+K;
s+=(K+la)*(r-l+1)/2;
lyk+=K;
lyd+=D;
}
}t[MAX<<2];
int N,M;
int a[MAX];
void pushdown(int now,int l,int r)
{
if(!t[now].lyd&&!t[now].lyk)return;
int mid=(l+r)>>1;
t[lson].put(lson,l,mid,t[now].lyk,t[now].lyd);
t[rson].put(rson,mid+1,r,t[now].lyk+(mid-l+1)*t[now].lyd,t[now].lyd);
t[now].lyd=t[now].lyk=0;
}
void update(int now,int l,int r,int al,int ar,int K,int D)
{
pushdown(now,l,r);
if(l==al&&r==ar){t[now].put(now,l,r,K,D);}
else
{
int la=(ar-al)*D+K;
t[now].s+=(K+la)*(ar-al+1)/2;
int mid=(l+r)>>1;
if(ar<=mid)update(lson,l,mid,al,ar,K,D);
else if(al>mid)update(rson,mid+1,r,al,ar,K,D);
else
{
update(lson,l,mid,al,mid,K,D);
update(rson,mid+1,r,mid+1,ar,K+(mid+1-al)*D,D);
}
}
}
int query(int now,int l,int r,int ll,int rr)
{
int cur_ans=0;
pushdown(now,l,r);
if(ll<=l&&r<=rr) return t[now].s;
int mid=(l+r)>>1;
if(ll<=mid) cur_ans+=query(lson,l,mid,ll,rr);
if(mid<rr) cur_ans+=query(rson,mid+1,r,ll,rr);
return cur_ans;
}
int main()
{
freopen("ce.in","r",stdin);
scanf("%d%d",&N,&M);
for(int i=1;i<=N;i++) scanf("%d",&a[i]);
for(int i=1;i<=N;i++) a[i]+=a[i-1];
int opt;
while(M--)
{
scanf("%d",&opt);
if(opt==1)
{
int L,R,K,D;
scanf("%d%d%d%d",&L,&R,&K,&D);
update(1,1,N,L,R,K,D);
}
else
{
int p,q;
scanf("%d%d",&p,&q);
printf("%d\n",query(1,1,N,p,q)+a[q]-a[p-1]);
}
}
return 0;
}
Luogu1438 无聊的数列(单点查询)&&加强版(区间查询)的更多相关文章
- LUOGU1438无聊的数列
区间加等差数列单点查询 思路: 差分,通过树状数组修改,然后保存两个数组,一个存公差,一个存和 然后正常操作即可 在学校潦草写的很潦草啦 代码如下: #include<cstdio> #i ...
- luogu1438无聊的数列(区间加等差数列,求一个数的和)
QAQ一道线段树好题 题目大意: 给定一个有n个数的数列,共m种操作,有两种操作 \(1\ l\ r\ k\ d\)表示将\(a[l]\)~\(a[r]\)的数加一个以k为首相,d为公差 \(2\ x ...
- [luogu1438]无聊的数列
考虑令$b_{i}=a_{i+1}-a_{i}$,那么1操作相当于对L加上K,对(L,R]区间加上D,对R+1减去K+(R-L)*D,然后询问区间和即可 1 #include<bits/stdc ...
- Libre OJ 130、131、132 (树状数组 单点修改、区间查询 -> 区间修改,单点查询 -> 区间修改,区间查询)
这三题均可以用树状数组.分块或线段树来做 #130. 树状数组 1 :单点修改,区间查询 题目链接:https://loj.ac/problem/130 题目描述 这是一道模板题. 给定数列 a[1] ...
- LOJ #6283. 数列分块入门 7-分块(区间乘法、区间加法、单点查询)
#6283. 数列分块入门 7 内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 2 题目描述 给出 ...
- LOJ #6282. 数列分块入门 6-分块(单点插入、单点查询、数据随机生成)
#6282. 数列分块入门 6 内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 1 题目描述 给出 ...
- LOJ #6277. 数列分块入门 1-分块(区间加法、单点查询)
#6277. 数列分块入门 1 内存限制:256 MiB时间限制:100 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 2 题目描述 给出 ...
- 洛谷P1438 无聊的数列 [zkw线段树]
题目传送门 无聊的数列 题目背景 无聊的YYB总喜欢搞出一些正常人无法搞出的东西.有一天,无聊的YYB想出了一道无聊的题:无聊的数列...(K峰:这题不是傻X题吗) 题目描述 维护一个数列{a[i]} ...
- [luogu P1438] 无聊的数列
[luogu P1438] 无聊的数列 题目背景 无聊的YYB总喜欢搞出一些正常人无法搞出的东西.有一天,无聊的YYB想出了一道无聊的题:无聊的数列...(K峰:这题不是傻X题吗) 题目描述 维护一个 ...
随机推荐
- OpenMP 旅行商问题,静态调度
▶ <并行程序设计导论>第六章中讨论了旅行商,分别使用了 MPI,Pthreads,OpenMP 来进行实现,这里是 OpenMP 的代码,分为静态调度(每个线程分分配等量的搜索人物)和动 ...
- Python 使用 Postfix 发送邮件
最近在做一个监控程序,需要用邮件发送告警.以前是使用注册的免费邮来发送,但是这样不免有很多限制,而且有时还会当作恶意登录,帐号异常等,还不让登录邮箱了.利用Postfix提供邮件SMTP服务,可以很自 ...
- Nginx 实现 IP+项目名 访问
参考: https://blog.csdn.net/csdn1152789046/article/details/51362735 修改前 项目放在Tomcat的webapps/ROOT/ 目录下面 ...
- 为什么nginx error_page遇到后端错误时不跳转?
nginx不得不说的参数之 proxy_intercept_errors与fastcgi_intercept_errors 为什么我的error_page 配置没有生效,没有正常跳转?我也遇到过这个问 ...
- 为什么需要maven,maven能解决什么问题 ,maven是什么
- 【Git】三、工作区、暂存区、版本库
一.基础概念 工作区:电脑中可以看到的目录,为电脑中的项目文件 暂存区:暂存修改的地方 版本库:存放项目的各个版本文件 二.详细介绍 工作区为我们工作所使用的目录,在工作区我们对项目文件进行增删改查. ...
- 第七章 二叉搜索树 (a)概述
- win10,python连接mysql报”Can't connect to MySQL server on 'localhost' (10061)”
一.环境及问题描述 1. 环境 操作系统:win10家庭版,64bit python版本:Python 2.7.15 mysql版本:mysql 5.4.3 2. 问题描述 最近跟公司申请电脑,预装w ...
- 这样的UX设计师简历,HR分分钟给你来电话
BLS调查显示,软件开发和IT,用户体验设计,产品经理和项目管理这三个职位在未来有非凡的发展前景.其中,用户体验设计师是目前最有需求的创意产业工作之一.10年里就业增长率高达22.1%,工作岗位数3, ...
- 5 Django-2 的路由层 (URLconf)
URL 配置 (URLconf) 就像 Django 所支撑网站的目录.它的本质是 URL 与要为该 URL 调用的视图函数之间的映射表:你就是以这种方式告诉 Django,对于客户端发来的某个 UR ...