线段树递归和非递归实现+hdu1166 敌兵布阵
递归代码:
#include <string>
#include <cstring>
#include <iostream>
#include <stdio.h>
using namespace std;
const int inf=1e5+7; //最多的数量。
int sum[inf<<2],add[inf<<2]; //其中的值都为零。
int arr[inf],n;void PushUp(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];} //应该是按照顺序进行的吧。
void BuiltTree(int l,int r,int rt) //建树。
{if(l==r) //说明是到达了叶子结点。{sum[rt]=arr[l];return ;}int m=(l+r)>>1;BuiltTree(l,m,rt<<1);BuiltTree(m+1,r,rt<<1|1);PushUp(rt);
}
//点修改,A[L]+=C;
void UpDate(int l,int r,int L,int C,int rt)
{if(l==r){sum[rt]+=C; //这里。return ;}int m=(l+r)>>1;if(L<=m)UpDate(l,m,L,C,rt<<1);elseUpDate(m+1,r,L,C,rt<<1|1);PushUp(rt);
}
//下推标志。
void PushDown(int l,int r,int rt)
{if(add[rt]){int m=(l+r)>>1;sum[rt<<1]+=(m-l+1)*add[rt];sum[rt<<1|1]+=(r-m)*add[rt];add[rt<<1]+=add[rt];add[rt<<1|1]+=add[rt];add[rt]=0;}
}
//区间修改,A[L到R]+=C;
void UpDate1(int l,int r,int rt,int L,int R,int C) //有可能有多次修改。所以每到一个结点都要下推标志。
{if(l>=L&&r<=R){sum[rt]+=(r-l+1)*C;add[rt]+=C;return ;}PushDown(l,r,rt);int m=(l+r)>>1;if(L<=m)UpDate1(l,m,rt<<1,L,R,C);if(R>m)UpDate1(m+1,r,rt<<1|1,L,R,C);PushUp(rt);
}
//区间查询。 求arr[L到R]的和。
int DateQuery(int l,int r,int rt,int L,int R)
{if(l>=L&&r<=R){return sum[rt];}PushDown(l,r,rt);int m=(l+r)>>1;int ans=0; //如果数据过大的话用long long.if(L<=m)ans+=DateQuery(l,m,rt<<1,L,R);if(R>m)ans+=DateQuery(m+1,r,rt<<1|1,L,R);return ans;
}
void display()
{for(int i=1;i<=4*n;i++)printf("%d ",sum[i]);printf("\n");
}int main()
{cout<<"请输入数组的个数"<<endl;cin>>n;cout<<"请输入数据"<<endl;for(int i=1;i<=n;i++){scanf("%d",&arr[i]);}BuiltTree(1,n,1);display();int flag=0;cout<<"是否进行点修改?是,1;否,0"<<endl;cin>>flag;if(flag==1){int C,L;cout<<"请输入要修改的点和数据"<<endl;cin>>L>>C;UpDate(1,n,L,C,1);display();}cout<<"是否进行区间修改,是,1:否,0"<<endl;cin>>flag;if(flag==1){int L,R,C;cout<<"请输入左右区间和数据"<<endl;cin>>L>>R>>C;UpDate1(1,n,1,L,R,C);display();}cout<<"是否进行区间求和,是,1:否,0"<<endl;cin>>flag;if(flag==1){int L,R;cout<<"请输入左右端点"<<endl;cin>>L>>R;cout<<"结果是"<<endl;cout<<DateQuery(1,n,1,L,R)<<endl;}return 0;
}
非递归代码:
#include <iostream> //线段树。
#include <cstring>
#include <string>
using namespace std;
const int inf=100007;
int Sum[inf<<2]; //初始的应该是零吧。
int Add[inf<<2];
int A[inf];
int n,N;
void Build(int n) //首先进行创建。
{ N=1;while(N<n+2)N<<=1; //首先找出N来。 for(int i=1;i<=n;i++) Sum[i+N]=A[i]; //之后看看两边的还要管吗。 for(int i=N-1;i>0;i--) { Sum[i]=Sum[i<<1]+Sum[i<<1|1]; Add[i]=0; //在这里进行修改吗。 }
}
void Update(int L,int C) //之后是进行点修改。sum[l]+=C;
{ for(int s=L+N;s;s>>=1) { Sum[s]+=C; }
}
int Query(int L,int R) //点修改下的区间查询。sum[L R]的和。
{ int ans=0; for(int s=L+N-1,t=R+N+1;s^t^1;s>>=1,t>>=1) { if(~s&1)ans+=Sum[s^1]; if(t&1)ans+=Sum[t^1]; } return ans;
}
void Update1(int L,int R,int C) //区间修改Sum[L R]+=C;
{ int s,t,Ln=0,Rn=0,x=1; for(s=L+N-1,t=R+N+1;s^t^1;s>>=1,t>>=1,x<<=1 ) { Sum[s]+=Ln*C; Sum[t]+=Ln*C; //这里。 if(~s&1)Add[s^1]+=C,Sum[s^1]+=C*x,Ln+=x; if(t&1) Add[t^1]+=C,Sum[t^1]+=C*x,Rn+=x; } for( ;s;s>>=1,t>>=1) //链接还是巧妙的啊。 { Sum[s]+=C*Ln; Sum[t]+=C*Rn; }
}
int Query1(int L,int R) //区间修改上的区间查询。sum【L,R】的和。
{ int s,t,Ln=0,Rn=0,x=1; int ans=0; for(s=L+N-1,t=R+N+1;s^t^1;s>>=1,t>>=1,x<<=1) { if(Add[s])ans+=Add[s]*Ln; if(Add[t])ans+=Add[t]*Rn; if(~s&1)ans+=Sum[s^1],Ln+=x; if( t&1)ans+=Sum[t^1],Rn+=x; } for( ;s;s>>=1,t>>=1) //其实加不加是无所谓的。 { /*if( Add[s])*/ans+=Add[s]*Ln; //这里为何是不加的呢。 /*if( Add[t])*/ans+=Add[t]*Rn; } return ans;
}int main()
{ cout<<"请输入数组的个数"<<endl; cin>>n; cout<<"请输入数组中的值"<<endl; for(int i=1;i<=n;i++) cin>>A[i]; Build(n); //初始化。 for(int i=1;i<=2*N-1;i++) cout<<Sum[i]<<" "; cout<<endl; Update(3,1); for(int i=1;i<=2*N-1;i++) cout<<Sum[i]<<" "; cout<<endl; int ans=Query(2,4); cout<<ans<<endl; Update1(2,4,1); for(int i=1;i<=2*N-1;i++) cout<<Sum[i]<<" "; cout<<endl; int ans1=Query1(1,4); //最后一个。 cout<<ans1<<endl; return 0;
}
hdu1166 敌兵布阵
http://acm.hdu.edu.cn/showproblem.php?pid=1166
简单线段树点修改和区间查询:
代码:
#include <string>
#include <cstring>
#include <iostream>
#include <stdio.h>
using namespace std;
const int inf=1e5+7; //最多的数量。
int sum[inf<<2],add[inf<<2]; //其中的值都为零。
int arr[inf],n;void PushUp(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];} //应该是按照顺序进行的吧。
void BuiltTree(int l,int r,int rt) //建树。
{if(l==r) //说明是到达了叶子结点。{sum[rt]=arr[l];return ;}int m=(l+r)>>1;BuiltTree(l,m,rt<<1);BuiltTree(m+1,r,rt<<1|1);PushUp(rt);
}
//点修改,A[L]+=C;
void UpDate(int l,int r,int L,int C,int rt)
{if(l==r){sum[rt]+=C; //这里。return ;}int m=(l+r)>>1;if(L<=m)UpDate(l,m,L,C,rt<<1);elseUpDate(m+1,r,L,C,rt<<1|1);PushUp(rt);
}
//下推标志。
void PushDown(int l,int r,int rt)
{if(add[rt]){int m=(l+r)>>1;sum[rt<<1]+=(m-l+1)*add[rt];sum[rt<<1|1]+=(r-m)*add[rt];add[rt<<1]+=add[rt];add[rt<<1|1]+=add[rt];add[rt]=0;}
}
//区间修改,A[L到R]+=C;
void UpDate1(int l,int r,int rt,int L,int R,int C) //有可能有多次修改。所以每到一个结点都要下推标志。
{if(l>=L&&r<=R){sum[rt]+=(r-l+1)*C;add[rt]+=C;return ;}PushDown(l,r,rt);int m=(l+r)>>1;if(L<=m)UpDate1(l,m,rt<<1,L,R,C);if(R>m)UpDate1(m+1,r,rt<<1|1,L,R,C);PushUp(rt);
}
//区间查询。 求arr[L到R]的和。
int DateQuery(int l,int r,int rt,int L,int R)
{if(l>=L&&r<=R){return sum[rt];}PushDown(l,r,rt);int m=(l+r)>>1;int ans=0; //如果数据过大的话用long long.if(L<=m)ans+=DateQuery(l,m,rt<<1,L,R);if(R>m)ans+=DateQuery(m+1,r,rt<<1|1,L,R);return ans;
}
void display()
{for(int i=1;i<=4*n;i++)printf("%d ",sum[i]);printf("\n");
}int main()
{int t;scanf("%d",&t);int abc=1;while(t--){printf("Case %d:\n",abc++);scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%d",&arr[i]);BuiltTree(1,n,1);string str;while(1){cin>>str;if(str=="End")break;int a,b;scanf("%d %d",&a,&b);if(str=="Query"){printf("%d\n",DateQuery(1,n,1,a,b));} else if(str=="Add")UpDate(1,n,a,b,1);else{b=-1*b;UpDate(1,n,a,b,1);} }}return 0;
}
线段树递归和非递归实现+hdu1166 敌兵布阵相关推荐
- 线段树版子题【HDU - 1166 敌兵布阵】【HDU-1754 I Hate It】【HDU-1698 Just a Hook】【OpenJ_Bailian3439A Simple Pro】
敌兵布阵 C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动 ...
- HDU1166 敌兵布阵【树状数组】
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- HDU1166 敌兵布阵(树状数组模板题)
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- hdu1166敌兵布阵 树状数组裸题
树状数组裸题 动态更新区间内的点,动态查询区间和 敌兵布阵 ac代码 #include<iostream> #include<algorithm> #include<cs ...
- HDU1166 敌兵布阵 单点更新 区间查询
敌兵布阵 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others) Total Submi ...
- 小小线段树 以HDU-1166 敌兵布阵为例
[异世界情绪]日文翻唱<鳥の詩/鸟之诗> 引个流,情绪的鸟之诗真的好听,听着这个学习效率巨高! 文章目录 前言 一.build函数 演示①和②: 二.add函数 演示③: 三.query函 ...
- hdu1166敌兵布阵hdu1754I Hate It(线段树入门)
单点更新是最最基础的线段树,只更新叶子节点,然后把信息用pushup这个函数更新上来. http://acm.hdu.edu.cn/showproblem.php?pid=1166 update单点更 ...
- hdu1166 敌兵布阵 线段树
C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况.由于 ...
- hdu-1166敌兵布阵
这个题目就是考察线段树的基本用法,我自己打了代码,其实就是照模板来的,大概思想已经弄懂了.用c++不能过,说我超时,就改成c的读入读出,这坑爹的过了.我最爱的c++,你肿么了... 这是ac的代码: ...
最新文章
- 画出降维后的图片_有没有人能画出《三体》里太阳系被二维化的概念图?
- UA MATH571A 检验异方差的非参数回归方法
- 中国鱼胶原蛋白行业应用前景与十四五投资建议报告2022年
- 双11稳定性负责人叔同讲述:九年双11的云化架构演进和升级
- P5020-货币系统【背包】
- 三大运营商5G预约用户数近9百万 5G商用进入倒计时
- OpenShift 4 - Knative教程(2) 基于Revision/Tag/Traffic实现蓝绿部署和恢复发布
- VMware vCenter Server Appliance Photon OS安全修补程序
- Vue编写动态组件实践(render函数的使用心得)
- redis版本_Redis—重要历史版本
- [Swift]LeetCode145. 二叉树的后序遍历 | Binary Tree Postorder Traversal
- Java图书管理系统
- Pr 视频效果:过渡、透视、通道
- eda课程设计,求救!!!!!!!!
- 木讷的程序员需要知道的事情 (三)
- QQ自由幻想刺客的属性点
- stimulsoft mysql_StimulSoft——将炫酷的报表写入你的应用程序
- calsite原理_Calcite 处理一条SQL - II (Rels Into Planner)
- opencv 图片上画一条线
- 代谢组学分析平台都有什么仪器?
热门文章
- 排序算法汇总(转载收藏)
- 虚拟机ping不通主机,但是主机可以ping通虚拟机(转载)
- xcart-子分类/语言不显示
- 设计模式原则(单一、开放封闭、里氏代换、依赖倒转、迪米特法则五大原则)...
- python中argparse模块
- 【网络】解决‘ipconfig不是内部或外部命令,也不是可运行的程序
- go flag包获取命令行参数使用示例
- Docker多阶段镜像构建Dockerfile脚本示例:构建nodejs前端项目
- 服务器上的hdfs的配置文件中,namenode不能设置成127.0.0.1或者localhost,要设置ip或者映射别名
- 【網址收藏】解决VSCODE“因为在此系统上禁止运行脚本“报错