2016.7.9 线段树(未完成版)
来源:互联网 发布:wifi无法连接这个网络 编辑:程序博客网 时间:2024/05/22 15:22
参考资料:
1.线段树课件(来自buctears;
2.线段树讲义(未注名
3.线段树+位总结(http://blog.csdn.net/byijie/article/details/8586499
4.poj2777题解 (http://blog.csdn.net/wuyanyi/article/details/7032305
5.线段树专辑(http://blog.sina.com.cn/s/articlelist_1763500727_6_1.html
从参考资料就可以看出,这次的学习比较艰难;
一.poj 3468 A Simple Problem with Integers
题意:改变值,查总和
题目分析:我一开始以为,这种线段树的几个操作都涉及了的(build,pushup,oushdown,update,query)题已经算是超级难的了,刚看完函数代码就写的我万分不自信,但因为喜欢自己思考,我硬生生地自己写了出来,很耗费心力......然而,后来我发现,在线段树里求和,真的太仁慈了......
#include<cstdio>#include<iostream>#include<cmath>#include<cstdlib>#include<cstring>#include<string>#include<algorithm>#include<queue>#include<set>using namespace std;const int MAXN=100005;int n,m,ll,rr;long long a[MAXN],ad;char cl;struct NODE{ long long add,sum; int rig,lef;}node[MAXN*8];void pushdown(int u){ node[u].sum+=node[u].add*(node[u].rig-node[u].lef+1); node[2*u].add+=node[u].add; node[2*u+1].add+=node[u].add; node[u].add=0; }void pushup(int k){ if(!node[2*k].add&&!node[2*k+1].add) node[k].sum=node[2*k].sum+node[2*k+1].sum; else if(!node[2*k].add) pushdown(2*k+1); else pushdown(2*k);}void build(int u,int l,int r){ node[u].lef=l;node[u].rig=r;node[u].add=0; if(l==r) { node[u].sum=a[l];//线段!树 return; } else {int mid=(l+r)/2; build(2*u,l,mid); build(2*u+1,mid+1,r); } pushup(u);//下先上后; }long long query(int u,long long z,long long y){ if(node[u].add)pushdown(u); int mid=(node[u].lef+node[u].rig)/2; if(node[u].lef==z&&node[u].rig==y) return node[u].sum; else if(z>mid)return query(2*u+1,z,y); else if(y<=mid)return query(2*u,z,y); else return query(2*u,z,mid)+query(2*u+1,mid+1,y);} void update(int u,long long zz,long long yy){ long long mid=(node[u].lef+node[u].rig)/2; node[u].sum+=(yy-zz+1)*ad;//+1 if(node[u].lef==zz&&node[u].rig==yy) { node[2*u].add+=ad; node[2*u+1].add+=ad; } else if(zz>mid) update(2*u+1,zz,yy); else if(yy<=mid) update(2*u,zz,yy); else { update(2*u,zz,mid); update(2*u+1,mid+1,yy); } }int main(){ freopen("aspi.in","r",stdin); freopen("aspi.out","w",stdout); ios::sync_with_stdio(false); cin>>m>>n;//a,q for(int i=1;i<=m;i++) //scanf("%I64d",&a[i]); cin>>a[i]; build(1,1,m); for(int i=1;i<=n;i++) { cin>>cl; switch (cl) { case 'Q': { cin>>ll>>rr; cout<<query(1,ll,rr)<<endl; break; } case 'C': { cin>>ll>>rr>>ad; update(1,ll,rr); break; } default:break; } } return 0;}
一般节点开四倍,我八倍才过是因为在update和pushdown里没有考虑叶子节点,即应分别改成
void pushdown(int u){ node[u].sum+=node[u].add*(node[u].rig-node[u].lef+1); if(node[u].lef!=node[u].rig) { node[2*u].add+=node[u].add; node[2*u+1].add+=node[u].add; } node[u].add=0; }
oid update(int u,long long zz,long long yy){ long long mid=(node[u].lef+node[u].rig)/2; node[u].sum+=(yy-zz+1)*ad;//+1 if(node[u].lef!=node[u].rig) { if(node[u].lef==zz&&node[u].rig==yy) { node[2*u].add+=ad; node[2*u+1].add+=ad; } else if(zz>mid) update(2*u+1,zz,yy); else if(yy<=mid) update(2*u,zz,yy); else { update(2*u,zz,mid); update(2*u+1,mid+1,yy); } }}
顺便,通过这次改错我学会了把其他只有几个模板之一的程序提交上去评测orz
特意强调“线段”树是因为我原来居然把lef,rig存成了左右子树节点......mdzz(手动再见
二.I hate it HDOJ1756
题意:单个改变,求最大
题目分析:除了坑爹的多数据输出害我改了很久以外,这是最没难度的,这道题开四倍也过了
#include<cstdio>#include<iostream>#include<cmath>#include<cstdlib>#include<cstring>#include<string>#include<algorithm>#include<queue>#include<set>using namespace std;const int MAXN=200005;int a[MAXN],m,n,l,r;char cl;struct STU{ int lef,rig,maxn;}stu[MAXN*4];void pushup(int u){ stu[u].maxn=max(stu[2*u].maxn,stu[2*u+1].maxn);}void build(int u,int l,int r){ stu[u].lef=l;stu[u].rig=r; int mid=(l+r)/2; if(l==r) { stu[u].maxn=a[l]; return; } else { build(2*u,l,mid); build(2*u+1,mid+1,r); pushup(u); }}int query(int u,int l,int r){ int mid=(stu[u].lef+stu[u].rig)/2; if(stu[u].lef==l&&stu[u].rig==r)return stu[u].maxn; else if(l>mid)return query(2*u+1,l,r); else if(r<=mid)return query(2*u,l,r); else return max(query(2*u,l,mid),query(2*u+1,mid+1,r));}void update(int u,int lookfor,int b){ int mid=(stu[u].lef+stu[u].rig)/2; if(stu[u].lef==stu[u].rig&&stu[u].lef==lookfor) { stu[u].maxn=b;return; } else if(lookfor<=mid)update(2*u,lookfor,b); else update(2*u+1,lookfor,b); pushup(u);}int main(){ freopen("hate.in","r",stdin); freopen("hate.out","w",stdout); ios::sync_with_stdio(false); while(cin>>n>>m) { for(int i=1;i<=n;i++) cin>>a[i]; build(1,1,n); for(int i=1;i<=m;i++) { cin>>cl; switch (cl) { case 'Q': { cin>>l>>r; cout<<query(1,l,r)<<endl; break; } case 'U': { cin>>l>>r; a[l]=r; update(1,l,r); break; } default: break; } } } return 0;}
三.lineup POJ3264
题意:不修改,找最大差距
题目分析:这道题做起来没有刚才那么得心应手,还是好好想了一下,因为不需要更改,这道题没有用到update和pushdown两个函数,想到用tallest和shortest来表示差异是关键;
#include<cstdio>#include<iostream>#include<cmath>#include<cstdlib>#include<cstring>#include<string>#include<algorithm>#include<queue>#include<set>using namespace std;const int MAXN=50005;int h[MAXN],n,t,s,q,l,r;struct COW{ int tallest,shortest,lef,rig;}cow[MAXN*4];void pushup(int u){ cow[u].tallest=max(cow[2*u].tallest,cow[2*u+1].tallest); cow[u].shortest=min(cow[2*u].shortest,cow[2*u+1].shortest);}void build(int u,int l,int r){ cow[u].lef=l;cow[u].rig=r; if(l==r) { cow[u].tallest=cow[u].shortest=h[l]; } else { int mid=(l+r)/2; build(2*u,l,mid); build(2*u+1,mid+1,r); pushup(u); }}void query(int u,int l,int r){ int mid=(cow[u].lef+cow[u].rig)/2; if(cow[u].lef==l&&cow[u].rig==r) { t=max(t,cow[u].tallest); s=min(s,cow[u].shortest); } else if(l>mid) query(2*u+1,l,r); else if(r<=mid) query(2*u,l,r); else { query(2*u,l,mid);query(2*u+1,mid+1,r); }}int main(){ freopen("lineup.in","r",stdin); freopen("lineup.out","w",stdout); ios::sync_with_stdio(false); cin>>n>>q; for(int i=1;i<=n;i++) cin>>h[i]; build(1,1,n); for(int i=1;i<=q;i++) { t=0;s=2e9; cin>>l>>r; query(1,l,r); cout<<t-s<<endl; } return 0;}
四.count color poj2777
题意:成段修改颜色,求颜色和
题目分析:这是遇到的第一道可怕的题!思考了基本方法以后我开始写,然后方法太复杂了基本没动力改,最后借助了题解......
很多题解都提到这是理解线段树的一道好题,值得写的程度很高,个人觉得比较难,自己写不出来的话可以好好咀嚼一下别人的程序(嘿!说你呢!快吐出来天辣夭寿啦)
- 2016.7.9 线段树(未完成版)
- 二叉树(未完成)
- 平衡树实现(未完成)
- android 9patch图片(未完成)
- java图形界面整理(未完成版)
- DTLS协议 RFC4347翻译(未完成版)
- Hibernate 实体关系映射(未完成版)
- 二叉树简单实现(未完成)
- 树与图(图 未完成)
- 2016.7.12 NOIP2013提高组day1解题报告(未完成版)
- 2016.7.12 NOIP2013提高组 day2解题报告(未完成版)
- 挂号控件 未完成版
- 查找 与 树(未完成)
- Linux设备树-未完成
- 一些想法(未完成)
- ADO简介(未完成)
- 初始化(未完成)
- 递归操作(未完成)
- Processon.com 只能保存到本地而无法保存到服务器的问题;
- URL与URI的区别
- sql查询将一对多转化为一对一
- 2016.7.12 NOIP2013提高组 day2解题报告(未完成版)
- 欢迎使用CSDN-markdown编辑器
- 2016.7.9 线段树(未完成版)
- 2016.7.13 树形动规
- 2016.7.13 一个小专题——RMQ算法
- 2016.7.14 noip2014模拟题 LGTB的日常~(自己乱安的名字hhh
- 第9周项目3 稀疏矩阵的三元组表示的实现及应用(2)
- 《React-Native系列》41、刨根问底Picker组件
- JAVA的pdf转图片方法
- 排序算法之交换排序
- 2016.7.15 落实字符及字符串读取的结果