区间修改与区间查询问题

模板:

int ans;

struct node{
int l,r,v;
node(){v=;}
}tree[LEN*];
int arr[LEN];
//建树
void build(int l,int r,int i){ //记录 [ l , r ]上的值,当前索引为 i
tree[i].l=l;
tree[i].r=r;
if(l==r){ //如果访问到了叶子节点
tree[i].v=arr[l]; //当前值就是arr[l,r]的值
return;
}
int m=(l+r)/; //二分
build(l,m,LS(i)); //左子树
build(m+,r,RS(i)); //右子树
tree[i].v=tree[LS(i)].v+tree[RS(i)].v; //递归建树出栈后,前驱结点的值为后继结点的和
}
//区间查询
void query(int i,int l,int r){ // i 为当前树的索引,初试化调用为 1 。查询 [ l , r ]区间上的和
if(tree[i].l>=l && tree[i].r<=r){ //如果查询区间包裹住了当前结点区间
ans+=tree[i].v; //直接加上这个结点的值
return;
}
if(l<=tree[LS(i)].r) //查询的 l 比左子树的右端点小
query(LS(i),l,r); //向左递归
if(r>=tree[RS(i)].l) //查询的 r 比右子树的左端点大
query(RS(i),l,r); //向右递归
}
//单点修改
void plus_i(int i,int p,int d){ //index(current) position delta
tree[i].v+=d; //当前结点的值更新
if(tree[i].l==tree[i].r) //访问到了叶子节点
return; //退出
if(p<=tree[LS(i)].r) //查询的 p 比左子树的右端点小
plus_i(LS(i), p,d);
if(p>=tree[RS(i)].l) //查询的 p 比右子树的左端点大
plus_i(RS(i), p,d);
}
//区间修改
void plus_s(int i,int l,int r,int d){
//取查询区间与结点区间的交集
int tl=max(l,tree[i].l);
int tr=min(r,tree[i].r);
if(tl<=tr) tree[i].v+=d*(tr-tl+); //如果这个交集合法,区间加
else return;
if(l<=tree[LS(i)].r) //查询的 l 比左子树的右端点小
plus_s(LS(i), l,r,d);
if(r>=tree[RS(i)].l) //查询的 r 比右子树的左端点大
plus_s(RS(i), l,r,d);
}

注:可以把上文的结构体拆写为3个数组

测试OJ:P3372 【模板】线段树 1

测试代码:(因为无lazy优化,只有70分。我理解不了lazy优化)

#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <map> #define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 100010
#define MAX 1<<30
#define V vector<int>
#define ll long long
#define LS(i) i<<1
#define RS(i) i<<1|1 using namespace std; int ans; struct node{
int l,r,v;
node(){v=;}
}tree[LEN*];
int arr[LEN];
//建树
void build(int l,int r,int i){ //记录 [ l , r ]上的值,当前索引为 i
tree[i].l=l;
tree[i].r=r;
if(l==r){ //如果访问到了叶子节点
tree[i].v=arr[l]; //当前值就是arr[l,r]的值
return;
}
int m=(l+r)/; //二分
build(l,m,LS(i)); //左子树
build(m+,r,RS(i)); //右子树
tree[i].v=tree[LS(i)].v+tree[RS(i)].v; //递归建树出栈后,前驱结点的值为后继结点的和
}
//区间查询
void query(int i,int l,int r){ // i 为当前树的索引,初试化调用为 1 。查询 [ l , r ]区间上的和
if(tree[i].l>=l && tree[i].r<=r){ //如果查询区间包裹住了当前结点区间
ans+=tree[i].v; //直接加上这个结点的值
return;
}
if(l<=tree[LS(i)].r) //查询的 l 比左子树的右端点小
query(LS(i),l,r); //向左递归
if(r>=tree[RS(i)].l) //查询的 r 比右子树的左端点大
query(RS(i),l,r); //向右递归
}
//单点修改
void plus_i(int i,int p,int d){ //index(current) position delta
tree[i].v+=d; //当前结点的值更新
if(tree[i].l==tree[i].r) //访问到了叶子节点
return; //退出
if(p<=tree[LS(i)].r) //查询的 p 比左子树的右端点小
plus_i(LS(i), p,d);
if(p>=tree[RS(i)].l) //查询的 p 比右子树的左端点大
plus_i(RS(i), p,d);
}
//区间修改
void plus_s(int i,int l,int r,int d){
//取查询区间与结点区间的交集
int tl=max(l,tree[i].l);
int tr=min(r,tree[i].r);
if(tl<=tr) tree[i].v+=d*(tr-tl+); //如果这个交集合法,区间加
else return;
if(l<=tree[LS(i)].r) //查询的 l 比左子树的右端点小
plus_s(LS(i), l,r,d);
if(r>=tree[RS(i)].l) //查询的 r 比右子树的左端点大
plus_s(RS(i), l,r,d);
} int main(){
// freopen("D:\\CbWorkspace\\ACM数据结构\\线段树\\模板1.txt","r",stdin);
int N,M,i,t,op,x,y,k;
I("%d%d",&N,&M);
for(i=;i<=N;i++){
I("%d",&arr[i]);
}
build(,N,);
while(M--){
I("%d%d%d",&op,&x,&y);
switch(op){
case :
I("%d",&k);
plus_s(,x,y,k);
break;
case :
ans=;
query(,x,y);
O("%d\n",ans);
break;
}
}
return ;
}

区间最大最小值查询问题

OJ 链接:P1198 [JSOI2008]最大数

AC代码:

#include <stdio.h>
#include <memory.h>
#include <math.h>
#include <string>
#include <vector>
#include <set>
#include <stack>
#include <queue>
#include <algorithm>
#include <map> #define I scanf
#define OL puts
#define O printf
#define F(a,b,c) for(a=b;a<c;a++)
#define FF(a,b) for(a=0;a<b;a++)
#define FG(a,b) for(a=b-1;a>=0;a--)
#define LEN 400010
#define MAX 1<<30
#define V vector<int>
#define ll long long
#define LS(i) i<<1
#define RS(i) i<<1|1 using namespace std; int ans; struct node{
int l,r,v;
node(){v=;}
}tree[LEN*]; //建树
void build(int l,int r,int i){ //记录 [ l , r ]上的值,当前索引为 i
tree[i].l=l;
tree[i].r=r;
tree[i].v=-MAX;
if(l==r){ //如果访问到了叶子节点
return;
}
int m=(l+r)/; //二分
build(l,m,LS(i)); //左子树
build(m+,r,RS(i)); //右子树
}
//区间查询
void query(int i,int l,int r){ // i 为当前树的索引,初试化调用为 1 。查询 [ l , r ]区间上的和
if(tree[i].l>=l && tree[i].r<=r){ //如果查询区间包裹住了当前结点区间
ans=max(ans,tree[i].v); //取最大值
return;
}
if(l<=tree[LS(i)].r) //查询的 l 比左子树的右端点小
query(LS(i),l,r); //向左递归
if(r>=tree[RS(i)].l) //查询的 r 比右子树的左端点大
query(RS(i),l,r); //向右递归
}
//单点修改
void plus_i(int i,int p,int d){ //index(current) position delta
tree[i].v=max(tree[i].v,d); //取最大值
if(tree[i].l==tree[i].r) //访问到了叶子节点
return; //退出
if(p<=tree[LS(i)].r) //查询的 p 比左子树的右端点小
plus_i(LS(i), p,d);
if(p>=tree[RS(i)].l) //查询的 p 比右子树的左端点大
plus_i(RS(i), p,d);
} int main(){
// freopen("D:\\CbWorkspace\\ACM数据结构\\线段树\\最大数.txt","r",stdin);
int N,D,t=,num,pos=;
build(,LEN,);
char buf[];
I("%d%d",&N,&D);
while(N--){
I("%s%d",buf,&num);
if(buf[]=='A'){
num+=t;
num%=D;
plus_i(,pos++,num);
}else{
if(num==){
O("%d\n",t=);
continue;
}
ans=-MAX;
query(,pos-num,pos-);
O("%d\n",t=ans);
}
}
return ;
}

线段树模板(无lazy优化)的更多相关文章

  1. UESTC - 1057 秋实大哥与花 线段树模板题

    http://acm.uestc.edu.cn/#/problem/show/1057 题意:给你n个数,q次操作,每次在l,r上加上x并输出此区间的sum 题解:线段树模板, #define _CR ...

  2. POJ3468:A Simple Problem with Integers(线段树模板)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 149972 ...

  3. 洛谷P3372线段树模板1——线段树

    题目:https://www.luogu.org/problemnew/show/P3372 线段树模板. 代码如下: #include<iostream> #include<cst ...

  4. [AHOI 2009] 维护序列(线段树模板题)

    1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec  Memory Limit: 64 MB Description 老师交给小可可一个维护数列的任务,现在小 ...

  5. hdu1754 I hate it线段树模板 区间最值查询

    题目链接:这道题是线段树,树状数组最基础的问题 两种分类方式:按照更新对象和查询对象 单点更新,区间查询; 区间更新,单点查询; 按照整体维护的对象: 维护前缀和; 维护区间最值. 线段树模板代码 # ...

  6. P3373 线段树模板

    好,这是一个线段树模板. #include <cstdio> using namespace std; ; long long int sum[N],tag1[N],tag2[N],mo; ...

  7. 线段树模板hdu 1754:I Hate It

    I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  8. POJ 3468 A Simple Problem with Integers(线段树模板之区间增减更新 区间求和查询)

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 140120 ...

  9. 【BZOJ4311】向量(线段树分治,斜率优化)

    [BZOJ4311]向量(线段树分治,斜率优化) 题面 BZOJ 题解 先考虑对于给定的向量集,如何求解和当前向量的最大内积. 设当前向量\((x,y)\),有两个不同的向量\((u1,v1),(u2 ...

随机推荐

  1. win10 mysql5.7.28 配置安装

    如果有服务,使用下面命令删除,管理员身份打开cmd : sc delete mysql 1.下载 https://dev.mysql.com/downloads/mysql/5.7.html 没有的O ...

  2. IDEA快速修复错误快捷键

    有的时候在IDEA中编写代码,会出现错误提示,比如需要处理异常 将光标移动到出错,也就是划红线的地方,行首会出现一个小灯泡,点击会出现图二,可以按照提示进行修复

  3. [.NET] 控制只启动单个指定外部程序

    独立观察员 2019 年 6 月 12 日 有的时候我们程序需要启动外部程序来配合实现某些功能,比如启动一个 Cef 相关程序来承载网页.那么如果那个外部程序并没有实现单例启动,我们程序去启动它的时候 ...

  4. C#中的一些对话框问题处理

    1. 对于打开文件对话框处理 #region 打开文件对话框 string StrPath; OpenFileDialog Flag = new OpenFileDialog(); Flag.Mult ...

  5. ADFS登录界面自定义

    最近在做identityServer3+ADFS 实现域账号第三方授权验证,发现一个问题,在我们网站跳转到域账户登录页面,这个页面有点不美观,那么我们改如何自定义这个登录界面呢? ADFS安装配置这里 ...

  6. 面试官都叫好的Synchronized底层实现,这工资开多少一个月?

    本文为死磕Synchronized底层实现第三篇文章,内容为重量级锁实现. 本系列文章将对HotSpot的synchronized锁实现进行全面分析,内容包括偏向锁.轻量级锁.重量级锁的加锁.解锁.锁 ...

  7. Codeforces 939A题,B题(水题)

    题目链接:http://codeforces.com/problemset/problem/939/A A题 A. Love Triangle time limit per test 1 second ...

  8. Mac OSX(Mac OS10.11) 安装 pwntools 失败的最新解决方案

    pwntools是一个 CTF 框架和漏洞利用开发库,用 Python 开发,由 rapid 设计,旨在让使用者简单快速的编写 exploit. 网上针对 Mac OS 的安装教程大多都是基于 pip ...

  9. 澄清Fundebug录屏技术的几点误会

    1. "视频"并非真的视频.也不是通过连续播放大量截图来实现 首先请大家观看这个视频: 视频中,当鼠标点击"场景重现",会立即播放一段"视频" ...

  10. 强大的 strace 工具

    什么是 strace strace是Linux环境下的一款程序调试工具,用来监察一个应用程序所使用的系统调用. Strace是一个简单的跟踪系统调用执行的工具.在其最简单的形式中,它可以从开始到结束跟 ...