ImageVerifierCode 换一换
格式:DOCX , 页数:78 ,大小:76.85KB ,
资源ID:8451503      下载积分:3 金币
快捷下载
登录下载
邮箱/手机:
温馨提示:
快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。 如填写123,账号就是123,密码也是123。
特别说明:
请自助下载,系统不会自动发送文件的哦; 如果您已付费,想二次下载,请登录后访问:我的下载记录
支付方式: 支付宝    微信支付   
验证码:   换一换

加入VIP,免费下载
 

温馨提示:由于个人手机设置不同,如果发现不能下载,请复制以下地址【https://www.bdocx.com/down/8451503.html】到电脑端继续下载(重复下载不扣费)。

已注册用户请登录:
账号:
密码:
验证码:   换一换
  忘记密码?
三方登录: 微信登录   QQ登录  

下载须知

1: 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。
2: 试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。
3: 文件的所有权益归上传用户所有。
4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
5. 本站仅提供交流平台,并不能对任何下载内容负责。
6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

版权提示 | 免责声明

本文(线段树详解C++版.docx)为本站会员(b****6)主动上传,冰豆网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知冰豆网(发送邮件至service@bdocx.com或直接QQ联系客服),我们立即给予删除!

线段树详解C++版.docx

1、线段树详解C+版线段树的定义及特征定义1:线段树线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点。一棵二叉树,记为T (a,b),参数a,b表示该节点表示区间a,b。区间的长度b-a记为L。递归定义Ta,b:若L0 :a, (a+b) div 2为 T的左儿子(a+b) div 2+1,b为T的右儿子。 若L=0 :T为一个叶子节点。 表示区间1, 5的线段树表示如下:线段树支持的操作有:构造,插入,查找,更新,删除;这些操作不一定都有,在实现上也不一定都是一个套路,这都取决于实际问题;实际上,通过在线段树节点上记录不同的信息,线段树可

2、以完成很多不同的任务;线段树的高度为logn,这也就使得线段树可以在O(lgn)的时间完成插入、查询、删除等操作。1、忠诚(TYVJ 1038)Description 老管家是一个聪明能干的人。他为财主工作了整整10年,财主为了让自已账目更加清楚。要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意。但是由于一些人的挑拨,财主还是对管家产生了怀疑。于是他决定用一种特别的方法来判断管家的忠诚,他把每次的账目按1,2,3编号,然后不定时的问管家问题,问题是这样的:在a到b号账中最少的一笔是多少?为了让管家没时间作假他总是一次问多个问题。Input输入中第一行有两个数m,n表示有m(m

3、 =100000)笔账,n表示有n个问题,n =100000。 第二行为m个数,分别是账目的钱数 后面n行分别是n个问题,每行有2个数字说明开始结束的账目编号。Output输出文件中为每个问题的答案。具体查看样例。Sample Input10 31 2 3 4 5 6 7 8 9 102 73 91 10Sample Output2 3 1参考程序:#include #include #include using namespace std;int n,m,i,k,x,y,num,a100000,f100000;struct ss int l,r,ls,rs,f,data;t400001;vo

4、id build(int l,int r) int h; num+; h=num; th.l=l; th.r=r; if(l!=r) th.ls=num+1; tnum+1.f=h; build(l,(l+r)/2); th.rs=num+1; tnum+1.f=h; build(l+r)/2)+1,r); th.data=min(tth.ls.data,tth.rs.data); else th.data=al;fl=h; int find(int h,int p,int q) int v; if(th.l=p)&(th.r=q) return(th.data); v=(th.l+th.r)

5、/2; if(qv) return(find(th.rs,p,q); return(min(find(th.ls,p,v),find(th.rs,v+1,q);int main() num=0; t1.f=0; scanf(%d%d,&m,&n); for(i=1;i=m;i+) scanf(%d,&ai); build(1,m); for(i=1;i=n-1;i+) scanf(%d%d,&x,&y); printf(%d ,find(1,x,y); scanf(%d%d,&x,&y); printf(%d,find(1,x,y); return 0; 2、忠诚2(TYVJ 1039)Des

6、cription 老管家是一个聪明能干的人。他为财主工作了整整10年,财主为了让自已账目更加清楚。要求管家每天记k次账,由于管家聪明能干,因而管家总是让财主十分满意。但是由于一些人的挑拨,财主还是对管家产生了怀疑。于是他决定用一种特别的方法来判断管家的忠诚,他把每次的账目按1,2,3编号,然后不定时的问管家问题,问题是这样的:在a到b号账中最少的一笔是多少?为了让管家没时间作假他总是一次问多个问题。 在询问过程中账本的内容可能会被修改Input输入中第一行有两个数m,n表示有m(m =100000)笔账,n表示有n个问题,n =100000。 接下来每行为3个数字,第一个p为数字1或数字2,第

7、二个数为x,第三个数为y 当p=1 则查询x,y区间当p=2 则改变第x个数为yOutput输出文件中为每个问题的答案。具体查看样例。Sample Input10 31 2 3 4 5 6 7 8 9 101 2 72 2 01 1 10Sample Output2 0题解一:#include #include #include using namespace std;int n,m,i,k,x,y,num,a100000,f100000;struct ss int l,r,ls,rs,f,data;t400001;void build(int l,int r) int h; num+; h=

8、num; th.l=l; th.r=r; if(l!=r) th.ls=num+1; tnum+1.f=h; build(l,(l+r)/2); th.rs=num+1; tnum+1.f=h; build(l+r)/2)+1,r); th.data=min(tth.ls.data,tth.rs.data); else th.data=al;fl=h; void rebuild(int x) if(x=0) return; if(tx.data!=min(ttx.ls.data,ttx.rs.data) tx.data=min(ttx.ls.data,ttx.rs.data); rebuild

9、(tx.f); void change(int m,int x) tfm.data=x; rebuild(tfm.f);int find(int h,int p,int q) int v; if(th.l=p)&(th.r=q) return(th.data); v=(th.l+th.r)/2; if(qv) return(find(th.rs,p,q); return(min(find(th.ls,p,v),find(th.rs,v+1,q);int main() int flag=1; num=0; t1.f=0; scanf(%d%d,&m,&n); for(i=1;i=m;i+) sc

10、anf(%d,&ai); build(1,m); for(i=1;i=n;i+) scanf(%d,&k); if(k=1) if(flag=1) scanf(%d%d,&x,&y); printf(%d,find(1,x,y); flag=0; else scanf(%d%d,&x,&y); printf( %d,find(1,x,y); if(k=2) scanf(%d%d,&x,&y); change(x,y); return 0; 3、线段树练习题目描述 :一行N个方格,开始每个格子里都有一个整数。现在动态地提出一些问题和修改:提问的形式是求某一个特定的子区间a,b中所有元素的和;修改

11、的规则是指定某一个格子x,加上或者减去一个特定的值A。现在要求你能对每个提问作出正确的回答。1N100000,,提问和修改的总数m10000条。输入描述 Input Description输入文件第一行为一个整数N,接下来是n行n个整数,表示格子中原来的整数。接下一个正整数m,再接下来有m行,表示m个询问,第一个整数表示询问代号,询问代号1表示增加,后面的两个数x和A表示给位置X上的数值增加A,询问代号2表示区间求和,后面两个整数表示a和b,表示要求a,b之间的区间和。输出描述 Output Description共m行,每个整数样例输入 Sample Input64 5 6 2 1 341

12、3 52 1 41 1 92 2 6样例输出 Sample Output2222数据范围及提示 Data Size & Hint1N100000, m10000 。参考程序:#include#includeusing namespace std;struct tree int l; int r; int ls; int rs; int sum;t500000;int n,m,i,k,x,y,num,a100000,f100000;bool flag;void build(int p1,int l,int r) int m,ii; tp1.l=l; tp1.r=r; m=(tp1.l+tp1.r

13、)/2; for(ii=l;ii=r;ii+) tp1.sum+=aii; if(l=r) return; build(2*p1,l,m); build(2*p1+1,m+1,r);void modify(int p,int x1,int y1) int m; if(tp.l=x1) tp.sum+=y1; if(tp.l=tp.r) return; m=(tp.l+tp.r)/2; if(m=x1) modify(2*p,x1,y1); else modify(2*p+1,x1,y1);int find(int h,int p,int q) int m; if(th.l=p)&(th.r=q

14、) return(th.sum); m=(th.l+th.r)/2; if(q=m+1) return(find(2*h+1,p,q); else return(find(2*h,p,m)+find(2*h+1,m+1,q);int main() scanf(%d,&m); for(i=1;i=m;i+) scanf(%d,&ai); build(1,1,m); scanf(%d,&n); for(i=1;i=n;i+) scanf(%d,&k); if(k=2) scanf(%d%d,&x,&y); printf(%dn,find(1,x,y); if(k=1) scanf(%d%d,&x,

15、&y); modify(1,x,y); return 0;4、线段树练习 2题目描述 Description给你N个数,有两种操作1:给区间a,b的所有数都增加X2:询问第i个数是什么?输入描述 Input Description第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数。如果第一个数是1,后接3个正整数a,b,X,表示在区间a,b内每个数增加X,如果是2,后面跟1个整数i, 表示询问第i个位置的数是多少。输出描述 Output Description对于每个询问输出一行一个答案样例输入 Sample Input312321 2 3

16、 22 3样例输出 Sample Output5数据范围及提示 Data Size & Hint数据范围1=n=1000001=q=100000参考程序:#include#includeusing namespace std;int n,q,a100001;struct data int l,r,x;tr400001;void build(int k,int s,int t) trk.l=s;trk.r=t; if(s=t)trk.x=as;return; int mid=(s+t)1; build(k1,s,mid); build(k1; if(b=mid)update(kmid)updat

17、e(k1|1,a,b,x); else update(k1,a,mid,x); update(k1; if(x=mid)return trk.x+ask(k1,x); else return trk.x+ask(k1|1,x); int main() scanf(%d,&n); for(int i=1;i=n;i+) scanf(%d,&ai); build(1,1,n); scanf(%d,&q); for(int i=1;i=q;i+) int t,a,b,x; scanf(%d,&t); if(t=1) scanf(%d%d%d,&a,&b,&x); update(1,a,b,x); e

18、lse scanf(%d,&x); printf(%dn,ask(1,x); return 0;4.1 线段树练习 3题目描述 Description给你N个数,有两种操作:1:给区间a,b的所有数增加X2:询问区间a,b的数的和。输入描述 Input Description第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,每行表示操作的个数,如果第一个数是1,后接3个正整数,表示在区间a,b内每个数增加X,如果是2,表示操作2询问区间a,b的和是多少。pascal选手请不要使用readln读入输出描述 Output Description对于每个询问输出一行一个答案样例输入 Sa

19、mple Input312321 2 3 22 2 3样例输出 Sample Output9数据范围及提示 Data Size & Hint数据范围1=n=2000001=q=200000参考程序:#include#includeusing namespace std;int n,q,a200001;struct data int l,r; long long sum; int tag;tr800001;void build(int k,int s,int t) trk.l=s;trk.r=t; if(s=t)trk.sum=as;return; int mid=(s+t)1; build(k

20、1,s,mid); build(k1|1,mid+1,t); trk.sum=trk1.sum+trk1|1.sum;void pushdown(int k) int x=trk.r-trk.l+1; trk1.tag+=trk.tag; trk1|1.tag+=trk.tag; trk1)*trk.tag; trk1)*trk.tag; trk.tag=0;void update(int k,int a,int b,int x) int l=trk.l,r=trk.r; if(a=l&r=b) trk.tag+=x; trk.sum+=(b-a+1)*x; return; if(trk.ta

21、g)pushdown(k); int mid=(l+r)1; if(b=mid)update(kmid)update(k1|1,a,b,x); else update(k1,a,mid,x); update(k1|1,mid+1,b,x); trk.sum=trk1.sum+trk1; if(b=mid)return ask(kmid)return ask(k1|1,a,b); else return (ask(k1,a,mid)+ask(k1|1,mid+1,b); int main() scanf(%d,&n); for(int i=1;i=n;i+) scanf(%d,&ai); bui

22、ld(1,1,n); scanf(%d,&q); for(int i=1;i=q;i+) int t,a,b,x; scanf(%d,&t); if(t=1) scanf(%d%d%d,&a,&b,&x); update(1,a,b,x); else scanf(%d%d,&a,&b); printf(%lldn,ask(1,a,b); return 0;5、简单题(easy)有一个n个元素的数组,每个元素初始均为0。有m条指令,要么让其中一段连续序列数字反转0变1,1变0(操作1),要么询问某个元素的值(操作2)。例如当n=20时,10条指令如下:操作回答操作后的数组1 1 10N/A111

23、111111100000000002 61111111111100000000002 120111111111100000000001 5 12N/A111100000011000000002 60111100000011000000002 150111100000011000000001 6 16N/A111101111100111100001 11 17N/A111101*010002 121111101111111000010002 6111110111111100001000【输入文件】输入文件easy.in第一行包含两个整数n,m,表示数组的长度和指令的条数,以下m行,每行的第一个数

24、t表示操作的种类。若t=1,则接下来有两个数L, R (L=R),表示区间L, R的每个数均反转;若t=2,则接下来只有一个数I,表示询问的下标。【输出文件】 每个操作2输出一行(非0即1),表示每次操作2的回答。【样例】easy.ineasy.out20 101 1 102 62 121 5 122 62 151 6 161 11 172 122 6100011【限制】50%的数据满足:1=n=1,000,1=m=10,000100%的数据满足:1=n=100,000,1=m=500,000这道题标准算法是用线段树来实现#include#include#include#include#include#include#includeusing namespace std;const int maxn=100005;struct node int a,b; bool lazy; Treemaxn*4;int N,M;void yin(int &x)

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1