gym102220H 差分+树状数组(区间修改和输出)
这题目很有意思,让我学会了树状数组的差分,更加深刻理解了树状数组
树状数组的差分写法
void add(int x,int k)
{
for (int i = x;i <= n;i += lowbit(i)) c[i] += k;
} int sum(int x)
{
int ans = ;
for (int i = x;i > ;i -= lowbit(i)) ans += c[i];
return ans;
} {
add(l,x);
add(r+,-x);
int zhi=sum(l)//就是a[l]的数值,前缀和。
}
题意:
很简单,输入n m
给n个a[i],代表每栋楼要造的高度
接下来m个操作
输入op
当op等于1的时候输入l,r,val
区间l,r之间增加val高度
当op等于2的时候输入l,r
求区间l,r,最小的工作时长(这个我语文不好,举例吧 1 3 2需要3个工作时长 1 3 2 5需要6个工作时长,1 3 2 5 -> 0 2 1 4 -> 0 1 0 3 -> 0 0 0 3 -> 0 0 0 2 -> 0 0 0 1 -> 0 0 0 0)
思路:
差分树状数组
a[i]原本的高度 b[i]=a[i]-a[i-1](前缀和) c[i]=b[i]>0?b[i]:0(后者比前者小,需要多出的工作时长)
所以答案就是 a[l]+(c[i]求和(l<i<r))
增加的val高度,a[l]用一个前缀和树状数组 add(val,l)add(-val,r+1)
维护c[i]的树状数组特殊判断(tql这里的思考判断,做题的时候就是这里没处理好,于是代码写不出来)
其实就是把每个建筑的递增高峰写出来,如果前者比后者大,后者那个位置就是0
#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<queue>
#include<stack>
#include<algorithm>
#include<stdio.h>
#include<map>
#include<set>
#define ll long long
#define lowbit(x) x&-x
using namespace std;
const int maxn=1e5+;
int n,m,a[maxn],b[maxn];
ll cnt[maxn],cn[maxn];
void add1(int zhi,int x){
for(int i=x;i<=n;i+=lowbit(i)){
cn[i]+=(ll)zhi;
}
}
void add2(int zhi,int x){
for(int i=x;i<=n;i+=lowbit(i)){
cnt[i]+=(ll)zhi;
}
}
ll geshu1(int x){
if(x==){return ;}
ll sum=;
for(int i=x;i>;i-=lowbit(i)){
sum+=cn[i];
}
return sum;
}
ll geshu2(int x){
if(x==){return ;}
ll sum=;
for(int i=x;i>;i-=lowbit(i)){
sum+=cnt[i];
}
return sum;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
for(int i=;i<=n;i++){
cnt[i]=,cn[i]=;
}
for(int i=;i<=n;i++){
scanf("%d",&a[i]);
b[i]=a[i]-a[i-];int tt=(b[i]>?b[i]:);
add1(b[i],i);
add2(tt,i);
}
for(int i=;i<=m;i++){
int op;
scanf("%d",&op);
if(op==){
int l,r,val;
scanf("%d%d%d",&l,&r,&val);
add1(val,l);add1(-val,r+);//差分
if(b[l]<){
int tt=-b[l];
if(tt<val){
add2(val-tt,l);
}
}
else{
add2(val,l);
}
b[l]+=val;
if(b[r+]>=){
int tt=min(b[r+],val);
add2(-tt,r+);
}
b[r+]-=val;
}
else{
int l,r;
scanf("%d%d",&l,&r);
printf("%lld\n",geshu2(r)-geshu2(l)+geshu1(l));
}
}
}
return ;
}
看了扩展
区间修改,单点输出
单点修改,区间输出
到区间修改和输出
tql(看了Top_Spirit博客)
数组cnt[n] 用来维护a[i]
a[1]+a[2]+...+a[n]= (c[1]) + (c[1]+c[2]) + ... + (c[1]+c[2]+...+c[n])
= n*c[1] + (n-1)*c[2] +... +c[n]
= n * (c[1]+c[2]+...+c[n]) - (0*c[1]+1*c[2]+...+(n-1)*c[n])
再维护一个数组cnt2[n],cnt2[i] = (i-1)*c[i]
a[1]+a[2]+...+a[n]=n*geshu1(cnt,n) - geshu2(cnt2,n)
add1( l , val);
add1(r + , -val);
add2( l , (l - ) * val);
add2 (r + , r* (-z));
gym102220H 差分+树状数组(区间修改和输出)的更多相关文章
- 【bzoj3132】上帝造题的七分钟 二维树状数组区间修改区间查询
题目描述 “第一分钟,X说,要有矩阵,于是便有了一个里面写满了0的n×m矩阵. 第二分钟,L说,要能修改,于是便有了将左上角为(a,b),右下角为(c,d)的一个矩形区域内的全部数字加上一个值的操作. ...
- 【bzoj5173】[Jsoi2014]矩形并 扫描线+二维树状数组区间修改区间查询
题目描述 JYY有N个平面坐标系中的矩形.每一个矩形的底边都平行于X轴,侧边平行于Y轴.第i个矩形的左下角坐标为(Xi,Yi),底边长为Ai,侧边长为Bi.现在JYY打算从这N个矩形中,随机选出两个不 ...
- 【bzoj3110】[Zjoi2013]K大数查询 整体二分+树状数组区间修改
题目描述 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c.如果是2 a b c形式,表示询问从第a个位置到第b个位置,第C大的数 ...
- 【bzoj4540】[Hnoi2016]序列 单调栈+离线+扫描线+树状数组区间修改区间查询
题目描述 给出一个序列,多次询问一个区间的所有子区间最小值之和. 输入 输入文件的第一行包含两个整数n和q,分别代表序列长度和询问数.接下来一行,包含n个整数,以空格隔开,第i个整数为ai,即序列第i ...
- 【bzoj3779】重组病毒 LCT+树上倍增+DFS序+树状数组区间修改区间查询
题目描述 给出一棵n个节点的树,每一个节点开始有一个互不相同的颜色,初始根节点为1. 定义一次感染为:将指定的一个节点到根的链上的所有节点染成一种新的颜色,代价为这条链上不同颜色的数目. 现有m次操作 ...
- bzoj 3779 重组病毒 —— LCT+树状数组(区间修改+区间查询)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3779 RELEASE操作可以对应LCT的 access,RECENTER则是 makeroo ...
- 【BZOJ3110】【整体二分+树状数组区间修改/线段树】K大数查询
Description 有N个位置,M个操作.操作有两种,每次操作如果是1 a b c的形式表示在第a个位置到第b个位置,每个位置加入一个数c 如果是2 a b c形式,表示询问从第a个位置到第b个位 ...
- 【POJ3468】【树状数组区间修改】A Simple Problem with Integers
Description You have N integers, A1, A2, ... , AN. You need to deal with two kinds of operations. On ...
- 1082 线段树练习 3 && 树状数组区间修改区间查询
1082 线段树练习 3 题意: 给定序列初值, 要求支持区间修改, 区间查询 Solution 用树状数组, 代码量小, 空间占用小 巧用增量数组, 修改时在 \(l\) 处 $ + val$ , ...
随机推荐
- mongo shell远程连接使用数据库
mongo mydb --username user1 --host --password --username 用户名 --host 连接ip --port 连接端口号 --password 密码 ...
- Makefile中的wildcard/notdir/patsubst
在Makefile规则中,通配符会被自动展开. 但在变量的定义和函数引用时,通配符将失效.这种情况下如果需要通配符有效,就需要使用函数“wildcard”,它的用法是:$(wildcard PATTE ...
- codeforces C. Primes and Multiplication(快速幂 唯一分解定理)
题目链接:http://codeforces.com/contest/1228/problem/C 题解:给定一个函数f,g,题目有描述其中的表达式含义和两者之间的关系. 然后计算: 首先把给定的x用 ...
- 同步块:synchronized(同步监视器对象){同步运行代码片段}
package seday10; import seday03.Test2; /** * @author xingsir * 同步块:synchronized(同步监视器对象){需要同步运行的代码片段 ...
- P1558 色板游戏 线段树(区间修改,区间查询)
题意: 给n,m,k,n长度,k个操作,m种颜色 操作C:输入A,B,C,区间[A,B]变成C颜色,可能A>B,所以要确保A<B 操作P:输入A,B,区间[A,B]的颜色种类 思路: 因为 ...
- python获取进程id号:
python获取进程id号: os.getpid()获取当前进程id os.getppid()获取父进程id
- js 页面滚动到指定位置
当页面的长度比较长时,如果进行刷新页面,我们希望能够在刷新完成页面之后,能够停留在当前位置,而不是从头再手动滚动到当前位置. 那么这样的效果如何实现呢?下面开始简单描写(由于博客园不支持效果展示,所以 ...
- 专题-集合-ConcurrentHashMap
本文介绍ConcurrentHashMap是线程安全的,但为什么却不用加锁的原因 一.ConcurrentHashMap简介 在jdk1.7中是采用Segment + HashEntry + Reen ...
- 普及C组第二题(8.1)
2000. [2015.8.6普及组模拟赛]Leo搭积木(brick) 题目: Leo是一个快乐的火星人,总是能和地球上的OIers玩得很high. 2012到了,Leo又被召回火星了 ...
- CSS控制 文字超出部分显示省略号
实现单行文本的溢出显示省略号, (需要加宽度width属来兼容部分浏览) <p style="width: 100px;overflow: hidden;white-space: no ...