[poj3468]A Simple Problem with Integers_线段树
A Simple Problem with Integers
题目大意:给出n个数,区间加、查询区间和。
注释:1<=n,q<=100,000.(q为操作次数)。
想法:嗯...学了这么长时间线段树,发现我tm竟然不会lazy标记??!好吧,看来线段树又要重新来了。
关于这道题,主要是联系lazy标记的使用。如果每一次查询的时间复杂度都输满nlogn,那么就gg了。线段树之所以快的原因在于我们在查询到一个可以代替原来查询区间一部分的节点,我们就在这个节点上打一个lazy标记。那么我就不需要继续想该节点之后去遍历。而一个lazy标记表示这个节点的所有子节点都进行了同样的操作。那么如果我在同一个节点处打两个lazy标记,本题是区间加法,我们需要将两个lazy标记相加。我们在需要遍历的时候发现一个节点有lazy标记,我们需要将lazy标记向下推。为什么?
因为我们打标记是为了节约时间,但是lazy标记下面的节点在当前时刻的值是没有发生更改的,所以若我们需要下面节点的值,则我就必须将上面的lazy标记向下推,就是pushdown。
我们发现这样的话最上面的lazy标记显然是最新的。紧接着,推下lazy标记之后,我们需要将lazy标记所影响的点的值上传给father,就是pushup。
如果最后存在一个节点,它仍然有lazy标记但是它始终没有没第二次查询或者修改,我们就节省了将lazy标记作用在它子树里的时间,这就是lazy标记节省时间的根本。
最后,附上丑陋的代码... ...
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define lson pos<<1
#define rson pos<<1|1
#define N 100010
using namespace std;
typedef long long ll;
ll lazy[4*N];
int high[N];
ll sum[4*N];
void build(int pos,int l,int r)//建树
{
int mid=(l+r)>>1;
if(l==r)
{
sum[pos]=high[l];
return;
}
build(lson,l,mid);
build(rson,mid+1,r);
sum[pos]=sum[lson]+sum[rson];//pushup
}
inline void pushdown(int pos,int l,int r)
{
if(lazy[pos])
{
int mid=(l+r)>>1;
sum[lson]+=(mid-l+1)*lazy[pos];//推标记
lazy[lson]+=lazy[pos];
sum[rson]+=(r-mid)*lazy[pos];
lazy[rson]+=lazy[pos];
lazy[pos]=0;
}
}
void fix(int pos,int l,int r,int x,int y,ll val)
{
int mid=(l+r)>>1;
if(x<=l&&r<=y)
{
lazy[pos]+=val;
sum[pos]+=(r-l+1)*val;
return;
}
pushdown(pos,l,r);
if(x<=mid)//OTZ ZTY
{
fix(lson,l,mid,x,y,val);
}
if(y>mid)//OTZ ZTY
{
fix(rson,mid+1,r,x,y,val);
}
sum[pos]=sum[lson]+sum[rson];//pushup
}
ll query(int pos,int l,int r,int x,int y)
{
int mid=(l+r)>>1;
ll temp=0;
if(x<=l&&r<=y)
{
return sum[pos];
}
pushdown(pos,l,r);
if(x<=mid)
{
temp+=query(lson,l,mid,x,y);
}
if(y>mid)
{
temp+=query(rson,mid+1,r,x,y);
}
return temp;
}
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&high[i]);
}
build(1,1,n);
char s[10];
for(int a,b,c,i=1;i<=m;i++)
{
scanf("%s",s);
if(s[0]=='Q')
{
scanf("%d%d",&a,&b);
printf("%lld\n",query(1,1,n,a,b));
}
else
{
scanf("%d%d%d",&a,&b,&c);
fix(1,1,n,a,b,c);
}
}
return 0;
}
小结:重新开始线段树qwq
[poj3468]A Simple Problem with Integers_线段树的更多相关文章
- poj3468 A Simple Problem with Integers (线段树区间最大值)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 92127 ...
- POJ3468 A Simple Problem with Integers(线段树延时标记)
题目地址http://poj.org/problem?id=3468 题目大意很简单,有两个操作,一个 Q a, b 查询区间[a, b]的和 C a, b, c让区间[a, b] 的每一个数+c 第 ...
- poj3468 A Simple Problem with Integers(线段树模板 功能:区间增减,区间求和)
转载请注明出处:http://blog.csdn.net/u012860063 Description You have N integers, A1, A2, ... , AN. You need ...
- POJ3468 A Simple Problem with Integers —— 线段树 区间修改
题目链接:https://vjudge.net/problem/POJ-3468 You have N integers, A1, A2, ... , AN. You need to deal wit ...
- 2018 ACMICPC上海大都会赛重现赛 H - A Simple Problem with Integers (线段树,循环节)
2018 ACM 国际大学生程序设计竞赛上海大都会赛重现赛 H - A Simple Problem with Integers (线段树,循环节) 链接:https://ac.nowcoder.co ...
- poj 3468 A Simple Problem with Integers 线段树 题解《挑战程序设计竞赛》
地址 http://poj.org/problem?id=3468 线段树模板 要背下此模板 线段树 #include <iostream> #include <vector> ...
- POJ 3468 A Simple Problem with Integers(线段树 成段增减+区间求和)
A Simple Problem with Integers [题目链接]A Simple Problem with Integers [题目类型]线段树 成段增减+区间求和 &题解: 线段树 ...
- POJ3648 A Simple Problem with Integers(线段树之成段更新。入门题)
A Simple Problem with Integers Time Limit: 5000MS Memory Limit: 131072K Total Submissions: 53169 Acc ...
- poj 3468 A Simple Problem with Integers 线段树第一次 + 讲解
A Simple Problem with Integers Description You have N integers, A1, A2, ... , AN. You need to deal w ...
随机推荐
- freemarker自定义标签报错(五)
freemarker自定义标签 1.错误描述 六月 05, 2014 11:40:49 下午 freemarker.log.JDK14LoggerFactory$JDK14Logger error 严 ...
- Parse Fatal Error at line 41 column 24: 元素类型 "url-pattern" 必须由匹配的结束标记 "</url-pattern>" 终止
1.错误描述 严重: Parse Fatal Error at line 41 column 24: 元素类型 "url-pattern" 必须由匹配的结束标记 "< ...
- Linux显示更新十次后退出
Linux显示更新十次后退出 youhaidong@youhaidong-ThinkPad-Edge-E545:~$ top -n 10 top - 19:19:21 up 48 min, 2 use ...
- pat1011-1020
一开始几道题写到吐血,真的自己现在好弱 1011 水题不说了 #include<bits/stdc++.h> using namespace std; const int N = 105; ...
- JustMock .NET单元测试利器(三)用JustMock测试你的应用程序
用JustMock测试你的应用程序 本主题将指导您通过几个简单的步骤来使用Telerik®JustMock轻松测试您的应用程序.您将理解一个简单的原理,称为Arrange / Act / Assert ...
- Postman教程——发送第一个请求
系列文章首发平台为果冻想个人博客.果冻想,是一个原创技术文章分享网站.在这里果冻会分享他的技术心得,技术得失,技术人生.我在果冻想等待你,也希望你能和我分享你的技术得与失,期待. 前言 过年在家,闲来 ...
- MongoDB添加用户验证
Mongodb默认启动是不带认证,也没有账号,只要能连接上服务就可以对数据库进行各种操作,这样可不行.现在,我们得一步步开启使用用户和认证. 第一步,我们得定位到mongodb的安装目录.我本机的是C ...
- java保留小数点后位数以及输出反转数字
//方法一double b = 8.0/3.0; //与C语言不同,此处8.0和8有所区分 String format = String.format("%.2f,b"); //表 ...
- [BZOJ2467] [中山市选2010] 生成树 (排列组合)
Description 有一种图形叫做五角形圈.一个五角形圈的中心有1个由n个顶点和n条边组成的圈.在中心的这个n边圈的每一条边同时也是某一个五角形的一条边,一共有n个不同的五角形.这些五角形只在五角 ...
- linux优化项
Linux优化: 1.建立普通账号,使用普通用户登陆. 2.处理SELINUX. 3.处理防火墙. 4.精简开机自启动服务.保留sshd,network,crond,rsyslog,sysstat. ...