目录

  • 1275. 最大数【单点修改 区间最大】
  • 245. 你能回答这些问题吗【单点修改 / 区间内的最大连续字段】
  • 246. 区间最大公约数【区间修改 区间最大公约数】
  • P3372 【模板】线段树 1【区间修改,区间查询】
  • P2574 XOR的艺术【区间求1的个数 区间取反】
  • 247. 亚特兰蒂斯【扫描线 求矩阵的面积】

1275. 最大数【单点修改 区间最大】

#include<bits/stdc++.h>
using namespace std;
const int N=1e5*2+10;
struct node{int l,r,v;}tr[N*4];
int m,p;
void build(int u,int l,int r)//建树
{tr[u]={l,r};if(l==r) return;int mid=tr[u].l+tr[u].r>>1;build(u*2,l,mid);build(u*2+1,mid+1,r);
}
void pushup(int u)
{tr[u].v=max(tr[u*2].v,tr[u*2+1].v);
}
int query(int u,int l,int r)
{if(tr[u].l>=l&&tr[u].r<=r) return tr[u].v;//包含else{int v=0,mid=(tr[u].l+tr[u].r)/2;if(l<=mid) v=max(v,query(u*2,l,r));//左边有交集if(r>=mid+1) v=max(v,query(u*2+1,l,r));//右边有交集return v;}
}
void modify(int u,int x,int v)
//u是根,x是位置,v是值
{if(tr[u].l==x&&tr[u].r==x) tr[u].v=v;//叶子else{int mid=tr[u].l+tr[u].r>>1;if(x<=mid) modify(u*2,x,v);else modify(u*2+1,x,v);pushup(u);}
}
int main(void)
{cin>>m>>p;build(1,1,m);int last=0,n=0;for(int i=0;i<m;i++){char op; cin>>op;if(op=='Q'){int x; cin>>x;last=query(1,n-x+1,n);cout<<last<<endl;}else{int x; cin>>x;modify(1,n+1,(1ll*x+last)%p);n++;}}return 0;
}

245. 你能回答这些问题吗【单点修改 / 区间内的最大连续字段】

#include<bits/stdc++.h>
using namespace std;
const int N=1e5*5+10;
struct node
{int l,r;int sum,tmax,lmax,rmax;//sum: 区间和//tmax:整个区间的最大子段和//lmax:从左端点起的向右的最大子段和//rmax:从右端点起的向左的最大子段和
}tr[N*4];
int a[N],n,m;
void push(node& a,node& l,node& r)
{a.sum=l.sum+r.sum;a.tmax=max({l.tmax,r.tmax,l.rmax+r.lmax,l.sum+r.lmax,r.sum+l.rmax,});a.lmax=max({l.lmax,l.sum+r.lmax});a.rmax=max({r.rmax,r.sum+l.rmax});
}
void pushup(int u)
{push(tr[u],tr[u*2],tr[u*2+1]);
}
void build(int u,int l,int r)
{if(l==r) tr[u]={l,r,a[l],a[l],a[l],a[l]};else{tr[u]={l,r};int mid=l+r>>1;build(u*2,l,mid),build(u*2+1,mid+1,r);pushup(u);}
}
void modify(int u,int x,int v)
{if(tr[u].l==x&&tr[u].r==x) {tr[u]={x,x,v,v,v,v};}else{int mid=(tr[u].l+tr[u].r)/2;if(mid>=x) modify(u*2,x,v);else modify(u*2+1,x,v);pushup(u);}
}
node query(int u,int l,int r)
{if(l<=tr[u].l&&tr[u].r<=r) return tr[u];else {int mid=(tr[u].l+tr[u].r)/2;if(mid>=r) return query(u*2,l,r);else if(l>mid) return query(u*2+1,l,r);else{auto left=query(u*2,l,r);auto right=query(u*2+1,l,r);node res;push(res,left,right);return res;}}
}
int main(void)
{cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];build(1,1,n);for(int i=0;i<m;i++){int op,x,y; cin>>op>>x>>y;if(op==1){if(x>y) swap(x,y);auto temp=query(1,x,y);cout<<temp.tmax<<endl;}else modify(1,x,y);}return 0;
}

246. 区间最大公约数【区间修改 区间最大公约数】



上述题解的原处

#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1e5*5+10;
LL gcd(LL a,LL b){return b?gcd(b,a%b):a;}
struct node
{int l,r;LL sum,d;//sum区间总和,d区间最大公约数
}tr[N*4];
LL n,m,a[N];
void push(node& u,node& l,node& r)
{u.sum=l.sum+r.sum;u.d=gcd(l.d,r.d);
}
void pushup(int u)
{push(tr[u],tr[u*2],tr[u*2+1]);
}
void build(int u,int l,int r)
{if(l==r){LL b=a[l]-a[l-1];tr[u]={l,r,b,b};}else{tr[u]={l,r};int mid=l+r>>1;build(u*2,l,mid),build(u*2+1,mid+1,r);pushup(u);}
}
void modify(int u,int x,LL c)
{if(tr[u].l==x&&tr[u].r==x){tr[u].sum+=c,tr[u].d+=c;return;}else{int mid=(tr[u].l+tr[u].r)/2;if(mid>=x) modify(u*2,x,c);else modify(u*2+1,x,c);pushup(u);}
}
node query(int u,int l,int r)
{if(l<=tr[u].l&&tr[u].r<=r) return tr[u];else{int mid=(tr[u].l+tr[u].r)/2;if(mid>=r) return query(u*2,l,r);else if(l>=mid+1) return query(u*2+1,l,r);else{auto left=query(u*2,l,r);auto right=query(u*2+1,l,r);node res;push(res,left,right);return res;}}
}
int main(void)
{cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];build(1,1,n);for(int i=1;i<=m;i++){char op; cin>>op;if(op=='C'){LL l,r,d; cin>>l>>r>>d;modify(1,l,d);if(r+1<=n) modify(1,r+1,-d);}else{int l,r; cin>>l>>r;node right={0,0,0,0};auto left=query(1,1,l);if(l+1<=n) right=query(1,l+1,r);printf("%lld\n",labs(gcd(left.sum,right.d)));}}return 0;
}

P3372 【模板】线段树 1【区间修改,区间查询】

#include<bits/stdc++.h>
using namespace std;
typedef long long int LL;
const int N=1e5+10;
struct node
{int l,r;LL sum,add;
}tr[N*4];
LL a[N],n,m;
void pushup(int u)
{tr[u].sum=tr[u*2].sum+tr[u*2+1].sum;
}
void pushdown(int u)//根节点更新,子结点
{auto &ans=tr[u];auto &l=tr[u*2];auto &r=tr[u*2+1];if(ans.add){l.sum+=(l.r-l.l+1)*ans.add;r.sum+=(r.r-r.l+1)*ans.add;l.add+=ans.add;r.add+=ans.add;ans.add=0;}
}
void build(int u,int l,int r)
{if(l==r) tr[u]={l,r,a[l],0};else{int mid=(l+r)/2;tr[u]={l,r};build(u*2,l,mid),build(u*2+1,mid+1,r);pushup(u);}
}
void modify(int u,int l,int r,int d)
{if(l<=tr[u].l&&tr[u].r<=r){tr[u].sum+=1ll*(tr[u].r-tr[u].l+1)*d;tr[u].add+=d;}else{pushdown(u);int mid=(tr[u].l+tr[u].r)/2;if(l<=mid) modify(u*2,l,r,d);if(r>=mid+1) modify(u*2+1,l,r,d);pushup(u);}
}
LL query(int u,int l,int r)
{if(l<=tr[u].l&&tr[u].r<=r) return tr[u].sum;else{pushdown(u);LL sum=0;int mid=(tr[u].l+tr[u].r)/2;if(l<=mid) sum+=query(u*2,l,r);if(r>=mid+1) sum+=query(u*2+1,l,r);return sum;}
}
int main(void)
{cin>>n>>m;for(int i=1;i<=n;i++) cin>>a[i];build(1,1,n);for(int i=0;i<m;i++){int op; cin>>op;if(op==1){int l,r,d; cin>>l>>r>>d;modify(1,l,r,d);}else{int l,r; cin>>l>>r;cout<<query(1,l,r)<<endl;}}return 0;
}

P2574 XOR的艺术【区间求1的个数 区间取反】

#include<bits/stdc++.h>
using namespace std;
const int N=1e5*2+10;
struct node
{int l,r;int sum,add;//sum  1的个数
}tr[N*4];
int n,m,a[N];
char s[N];
void pushup(int u)
{tr[u].sum=tr[u*2].sum+tr[u*2+1].sum;
}
void pushdown(int u)
{if(tr[u].add) {tr[u*2].sum=(tr[u*2].r-tr[u*2].l+1)-tr[u*2].sum;tr[u*2+1].sum=(tr[u*2+1].r-tr[u*2+1].l+1)-tr[u*2+1].sum;tr[u*2].add^=1;tr[u*2+1].add^=1;tr[u].add=0; }
}
void build(int u,int l,int r)
{if(l==r) tr[u]={l,r,a[l],0};else{tr[u]={l,r};int mid=(l+r)/2;build(u*2,l,mid),build(u*2+1,mid+1,r);pushup(u);}
}
void modity(int u,int l,int r)
{if(l<=tr[u].l&&tr[u].r<=r){tr[u].sum=(tr[u].r-tr[u].l+1)-tr[u].sum;tr[u].add^=1;}else{pushdown(u);int mid=(tr[u].l+tr[u].r)/2;if(l<=mid) modity(u*2,l,r);if(r>=mid+1) modity(u*2+1,l,r);pushup(u);}
}
int query(int u,int l,int r)
{if(l<=tr[u].l&&tr[u].r<=r) return tr[u].sum;else{pushdown(u);int mid=(tr[u].l+tr[u].r)/2;int sum=0;if(l<=mid) sum+=query(u*2,l,r);if(r>=mid+1) sum+=query(u*2+1,l,r);return sum;}
}
int main(void)
{cin>>n>>m;for(int i=1;i<=n;i++) cin>>s[i];for(int i=1;i<=n;i++) a[i]=s[i]-'0';build(1,1,n);for(int i=0;i<m;i++){int op,l,r; cin>>op>>l>>r;if(op==0) modity(1,l,r);else cout<<query(1,l,r)<<endl;}return 0;
}

247. 亚特兰蒂斯【扫描线 求矩阵的面积】

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n;
struct Segment
{double x,y1,y2;bool operator< (const Segment &t)const{return x<t.x;}int k;
}seg[N*2];
struct Node
{int l,r;int cnt;//当前区间被覆盖的次数double len;//子区间总共被覆盖的长度
}tr[N*8];
vector<double>ys;int find(double y)
{return lower_bound(ys.begin(),ys.end(),y)-ys.begin();
}void pushup(int u)
{if(tr[u].cnt) tr[u].len=ys[tr[u].r+1]-ys[tr[u].l];else if(tr[u].l!=tr[u].r){tr[u].len=tr[u*2].len+tr[u*2+1].len; }else tr[u].len=0;
}void build(int u,int l,int r)
{tr[u]={l,r,0,0};if(l!=r){int mid=(l+r)/2;build(u*2,l,mid),build(u*2+1,mid+1,r);}
}void modify(int u,int l,int r,int k)
{if(l<=tr[u].l&&tr[u].r<=r){tr[u].cnt+=k;pushup(u);}else{int mid=(tr[u].l+tr[u].r)/2;if(l<=mid) modify(u*2,l,r,k);if(r>mid) modify(u*2+1,l,r,k);pushup(u);}
}int main()
{int t=1;while(scanf("%d",&n),n){ys.clear();for(int i=0,j=0;i<n;i++){double x1,y1,x2,y2; scanf("%lf%lf%lf%lf",&x1,&y1,&x2,&y2);seg[j++]={x1,y1,y2,1};seg[j++]={x2,y1,y2,-1};ys.push_back(y1),ys.push_back(y2);}sort(ys.begin(),ys.end());ys.erase(unique(ys.begin(),ys.end()),ys.end());build(1,0,ys.size()-2);sort(seg,seg+n*2);double res=0;for(int i=0;i<n*2;i++){if(i>0) res+=tr[1].len*(seg[i].x-seg[i-1].x);modify(1,find(seg[i].y1),find(seg[i].y2)-1,seg[i].k);}printf("Test case #%d\n",t++);printf("Total explored area: %.2lf\n\n", res);}
}

ACM入门之【线段树习题】相关推荐

  1. ACM入门之【树状数组】

    树状数组和线段树具有相似的功能,但他俩毕竟还有一些区别:树状数组能有的操作,线段树一定有:线段树有的操作, 树状数组不一定有.但是树状数组的代码要比线段树短,思维更清晰,速度也更快,在解决一些单点修改 ...

  2. 蒟蒻的ACM数据结构(一)-线段树

    浅谈线段树的指针写法 一.基本概念 二.代码实现与基本操作 0.基础数据结构 1.建树 built函数 2. 单点查询 3.单点修改 4.区间查询 5.区间修改 三.优化 (一). Lazy-Tag懒 ...

  3. ACM入门之【树状数组习题】

    目录 130. 树状数组 1 :单点修改,区间查询 131. 树状数组 2 :区间修改,单点查询 132. 树状数组 3 :区间修改,区间查询 133. 二维树状数组 1:单点修改,区间查询 134. ...

  4. ACM入门之【分块习题】

    目录 6277. 数列分块入门 1[区间修改 单点查询] 6278. 数列分块入门 2[区间加 区间查询小于x的个数] 6279. 数列分块入门 3[区间修改 区间查询小于x的最大值] 6277. 数 ...

  5. ACM入门之【图论习题】

    目录 P5318 [深基18.例3]查找文献[★ 图的遍历] P3916 图的遍历[★★ 求每一个点可以到达的最大的点 反向建图] P1113 杂务[★ ★ 拓扑排序 求完成所有杂务所需的最短时间] ...

  6. hdu1754(简单线段树)

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

  7. b+树时间复杂度_前端大神用的学习笔记:线段树和树状数组

    全文篇幅较长,细心理解一定会有收获的♪(^∇^*). 1|0线段树 1|1一些概念     线段树是一种二叉搜索树,每一个结点都是一个区间(也可以叫作线段,可以有单点的叶子结点),有一张比较形象的图如 ...

  8. 线段树 --算法竞赛专题解析(24)

    本系列文章将于2021年整理出版.前驱教材:<算法竞赛入门到进阶> 清华大学出版社 网购:京东 当当   作者签名书:点我 有建议请加QQ 群:567554289 文章目录 1. 线段树概 ...

  9. CF786B Legacy(线段树优化建边模板 + 最短路)

    整理的算法模板合集: ACM模板 目录 线段树优化建边 题目传送门 由于本题的数据达到了1e5,所以如果直接全部暴力连边的话会达到O(n2)O(n^2)O(n2),时间包括内存都受不了.因此我们需要使 ...

最新文章

  1. SpringMVC中数据库链接配置
  2. php 效率最高的递归,PHP 递归效率分析_PHP教程 - microtime
  3. Redis | 001能做什么?
  4. leetcode之Count and Say报数
  5. getResources()方法
  6. boost::fusion::erase_key用法的测试程序
  7. 物联网数据终端演进之道
  8. ueditor video 设置宽高的问题(uni app)
  9. 怎么查电脑系统版本_重装系统PE内找不到硬盘怎么办?只需要这些设置即可…...
  10. css多重背景教程,多重背景的CSS动画
  11. Thinkphp 生成数据表字段缓存
  12. LwIP协议栈之ARP(Address Resolution Protocal)协议详解
  13. 基于python的爬虫毕业论文_基于python网络爬虫及数据处理毕业论文 相关实例(示例源码)下载 - 好例子网...
  14. 许晓斌_Maven实战(三)——多模块项目的POM重构
  15. Codeforces Round #531 (Div. 3) F. Elongated Matrix (状态压缩dp)
  16. 我逢人就吹的超好用Markdown编辑器-Typora
  17. 电脑卡死,电脑卡屏死机几个原因与解决办法必看
  18. SpringBoot 集成 logBack
  19. NOIP训练 czy的后宫6(线性dp)
  20. 网站WEB都有哪些攻击?

热门文章

  1. JAVA_OA(五):SpringMVC接受传入页面的参数值
  2. 运行 vue 报node错
  3. python中多进程+协程的使用以及为什么要用它
  4. Android插件化开发之解决OpenAtlas组件在宿主的注冊问题
  5. Web云笔记--CSS
  6. 一款超炫的图片排列特效
  7. 通过飞行CALL找到BT飞行偏移 和飞行状态偏移
  8. 强碱性食品 高嘌呤食物
  9. Linux下FTP服务器配置与管理
  10. 整理:关于聚簇索引和非聚簇索引的区别