线段树3——一些例题的题解
这篇博客主要是由一些题目的题解构成的
1.XOR的艺术
https://www.luogu.org/problemnew/show/P2574
本题就是一个线段树的简单变形,把懒标记改成异或值就行了。
注意点:1.在下传标记的时候,区间值修改为区间总值减去原先值(t[rt].v=r-l+1-t[rt].v)
2.读入时用scanf("%1d"&t[rt].v);就行了
代码:
1 #include<bits/stdc++.h> 2 3 #define rd(x) x=read() 4 #define N 200005 5 6 using namespace std; 7 8 int n,m; 9 struct T{ 10 int l,r,mid,v,tag; 11 }t[N<<2]; 12 13 inline int read() 14 { 15 int f=1,x=0;char s=getchar(); 16 while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();} 17 while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();} 18 return x*f; 19 } 20 21 void pushdown(int rt,int len) 22 { 23 if(t[rt].tag) 24 { 25 t[rt<<1].tag^=1; 26 t[rt<<1|1].tag^=1;//异或 27 t[rt<<1].v=(len-(len>>1))-t[rt<<1].v; 28 t[rt<<1|1].v=(len>>1)-t[rt<<1|1].v;//t[rt].v=r-l+1-t[rt].v的变形 29 t[rt].tag=0; 30 } 31 } 32 33 void build(int rt,int l,int r) 34 { 35 int mid=(l+r)>>1; 36 t[rt].l=l,t[rt].r=r,t[rt].mid=mid,t[rt].tag=0; 37 if(l==r) 38 { 39 scanf("%1d",&t[rt].v); 40 return; 41 } 42 build(rt<<1,l,mid); 43 build(rt<<1|1,mid+1,r); 44 t[rt].v=t[rt<<1].v+t[rt<<1|1].v; 45 }//建树 46 47 void update(int rt,int l,int r) 48 { 49 if(l<=t[rt].l&&t[rt].r<=r) 50 { 51 t[rt].tag^=1; 52 t[rt].v=t[rt].r-t[rt].l+1-t[rt].v; 53 return; 54 } 55 pushdown(rt,t[rt].r-t[rt].l+1); 56 if(l<=t[rt].mid)update(rt<<1,l,r); 57 if(t[rt].mid<r)update(rt<<1|1,l,r); 58 t[rt].v=t[rt<<1].v+t[rt<<1|1].v; 59 }//更新 60 int query(int rt,int l,int r) 61 { 62 if(l<=t[rt].l&&t[rt].r<=r)return t[rt].v; 63 pushdown(rt,t[rt].r-t[rt].l+1); 64 int sum=0; 65 if(l<=t[rt].mid)sum+=query(rt<<1,l,r); 66 if(t[rt].mid<r)sum+=query(rt<<1|1,l,r); 67 return sum; 68 }//查询 69 70 int main() 71 { 72 rd(n),rd(m); 73 build(1,1,n); 74 while(m--) 75 { 76 int opt,l,r; 77 rd(opt),rd(l),rd(r); 78 if(opt)printf("%d\n",query(1,l,r)); 79 else update(1,l,r); 80 } 81 82 return 0; 83 }
温馨提醒:本题有多倍经验,在LGOJ上有另外三题
2.P1198 JSOI2008 最大数
https://www.luogu.org/problemnew/show/P1198
本题就是板子题目,只是稍微有一点思维性。
查询时,就是查询cnt-n+1——cnt的区间和(其中cnt代表当前的数列个数)
修改时,就是一个普通的单点修改(注意取模)
代码:
#include<bits/stdc++.h>#define rd(x) x=read() #define ll long longusing namespace std;ll m,d; ll ans; ll cnt;ll t[800005];inline ll read() {ll f=1,x=0;char s=getchar();while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}while(s>='0'&&s<='9'){x=x*10+s-'0';s=getchar();}return x*f; }void add(int rt,int l,int r,int x,int k) {if(l==r){t[rt]=k;return;}int mid=(l+r)>>1;if(x<=mid)add(rt<<1,l,mid,x,k);else add(rt<<1|1,mid+1,r,x,k);t[rt]=max(t[rt<<1],t[rt<<1|1])%d; }//类似建树的插入 int query(int rt,int l,int r,int x,int y) {int mid=(l+r)/2;if(x==l&&y==r)return t[rt];if(y<=mid)return query(rt<<1,l,mid,x,y);else if(x>mid)return query(rt<<1|1,mid+1,r,x,y);else return max(query(rt<<1,l,mid,x,mid),query(rt<<1|1,mid+1,r,mid+1,y)); }//查询 int main() {rd(m),rd(d);char opt[5];ll n;for(int i=1;i<=m;i++){scanf("%s",opt);//神奇读入方法,在这提一下,如果不想用getchar或scanf("%c ")可以用这种方法 rd(n);if(opt[0]=='A')add(1,1,m,++cnt,(n+ans)%d);//修改 else {if(n==0)ans=0;else ans=query(1,1,m,cnt-n+1,cnt)%d;//查询 cout<<ans<<endl;}}return 0; }
转载于:https://www.cnblogs.com/Robin20050901/p/10040699.html
线段树3——一些例题的题解相关推荐
- CCF202012-5 星际旅行【线段树】(100分题解链接)
试题编号: 202012-5 试题名称: 星际旅行 时间限制: 3.0s 内存限制: 512.0MB 问题描述: 题目描述 乔帝要规划一次星际旅行,星际空间可以视为一个3维坐标系,乔帝有n(n≤1,0 ...
- 线段树合并(四道例题)
顾名思义,就是合并两个同构(就是维护的区间长度一样)线段树,其实也没啥比较nb的算法,就是一个一个节点的合并,但是如果在n个要合并的线段树里,如果一共有m个元素,则配合动态开点,复杂度会均摊成一个惊人 ...
- 【总结】一些简单线段树题目的口胡题解
bzoj1645 离散化+扫描线 tyvj1473 校门外的树3 思维僵化(非要套离线枚举右端点然而不好做)系列,直接容斥求不与[l,r][l,r][l,r]相交的线段个数即可 bzoj3653谈笑风 ...
- c++自带的可持久化平衡树?rope大法好!(超详细解答 + 5道例题讲解,可直接替代可持久化的线段树、并查集、平衡树!)
整理的算法模板合集: ACM模板 目录 c++自带的可持久化平衡树?rope大法好! 1. 声明 2. 支持操作 char类型的rope int类型的rope 3. 具体的细节 4. "可持 ...
- 一些奇妙的线段树操作
学过数据结构和会做题完全是两个概念orz 各种各样的题目都应该见识一下 简单的目录: 最大连续长度 吉司机线段树 线段树合并/分裂 最大连续长度问题 典型题目:HDU 3911 ($Black$ $A ...
- 【BZOJ4991】我也不知道题目名字是什么(线段树)
[BZOJ4991]我也不知道题目名字是什么(线段树) 题面 BZOJ 题解 对于线段树维护的区间维护以下东西: 区间左(右)端开始(结束)的最长(短)子串的长度 左端右端的值,以及当前区间内的答案 ...
- 时空旅行[线段树分治][维护凸壳]
文章目录 前言 题目 思路 代码 前言 肝了一上午-这是我才学线段树分治的例题-真舒服 题目 温馨提示:首先在UOJ做,LOJ挖数据,BZOJ终极评测... UOJ198 二手剽- 思路 为什么不能用 ...
- 【LOJ#573】【LNR#2】单枪匹马(线段树)
[LOJ#573][LNR#2]单枪匹马(线段树) 题面 LOJ 题解 考虑拿线段树维护这个值,现在的问题就是左右怎么合并,那么就假设最右侧进来的那个分数是\(\frac{x}{y}\)的形式,那么就 ...
- 【题解】BZOJ 3065: 带插入区间K小值——替罪羊树套线段树
题目传送门 题解 orz vfk的题解 3065: 带插入区间K小值 系列题解 一 二 三 四 惨 一开始用了一种空间常数很大的方法,每次重构的时候merge两颗线段树,然后无限RE(其实是MLE). ...
最新文章
- CSS之定位(粘滞定位)
- 阿里云免费开放一切AI算力,加速新型冠状病毒新药和疫苗研发
- docker安装最新版Jenkins:拉取镜像/创建容器
- python递归详解_Python理解递归的方法总结
- 不同php文件,不同文件构建PHP程序的正确方式
- 最小二乘法2阶拟合数据
- Python脚本提取氨基酸序列的 因子复杂度
- 网络爬虫是什么意思?
- 布莱叶盲文-谷歌生态
- Powershell 添加开机启动项
- 无法识别服务器硬件信息,请教:无法获取服务器硬件信息
- mysql模糊搜索 like_Mysql必知必会(3):模糊查询(LIKE)
- [转载]軟件測試方法
- Python的namedtuple使用详解
- 7-8 病毒感染检测 (10分)
- 奥特曼系列ol进不去服务器,奥特曼系列OL闪退怎么办?解决方案
- python中selenium模块驱动谷歌详解
- 密歇根安娜堡计算机排名,密歇根大学的计算机系统排名,该细心来考查
- 【Unity 资源分享】 | Unity 精品写实动物模型+全套动画 资源分享
- 开放式激光振镜+运动控制器(六):双振镜运动