线段树最全模板
2017-11-02 15:10
309 查看
一定要做的线段树习题汇总
一、模板
if(ch[0]=='Q') printf("%d\n",query(1,n,1,a,b)); else update(1,n,1,a,b); } } return 0;}
二、区间查询,无单点更新
三、单点更新+区间求和
四、区间查询最值+单点更新
一、模板
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define MAXN 200010 #define lson l,mid,p<<1 #define rson mid+1,r,p<<1|1 int sum[MAXN<<2]; void pushUp(int p) { sum[p]=max(sum[p<<1],sum[p<<1|1]); } void build(int l,int r,int p) { if(l==r){ scanf("%d",&sum[p]); return ; } int mid=(l+r)>>1; build(lson); build(rson); pushUp(p); } int query(int l,int r,int p,int a,int b) { if(l>=a&&b>=r) //根据功能代码修改部分 return sum[p]; int ans=0; int mid=(l+r)>>1; if(mid>=a) ans=max(ans,query(lson,a,b)); //根据功能代码修改部分 if(mid<b) ans=max(ans,query(rson,a,b)); return ans; } void update(int l,int r,int p,int a,int b) { if(l==r){
//根据功能代码修改部分sum[p]=b; return ; } int mid=(l+r)>>1; if(a<=mid) update(lson,a,b); else update(rson,a,b); pushUp(p);}int main(){ int n,m; char ch[5]; //freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&m)) { int a,b; build(1,n,1); while(m--) { scanf("%s%d%d",ch,&a,&b);
if(ch[0]=='Q') printf("%d\n",query(1,n,1,a,b)); else update(1,n,1,a,b); } } return 0;}
二、区间查询,无单点更新
#include <iostream> #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; const int maxn=200010; int sum[maxn<<2];//数组开四倍 int h,w,n; //p表示下标 void pushUp(int p) { //p表示下标,赋值为两个儿子中的最大值 sum[p]=max(sum[p<<1],sum[p<<1|1]); } //建树 void build(int l,int r,int p) { if(l==r)//区间长度为0时结束递归 { sum[p]=w; return ; } //否则的话,分别递归左儿子和右儿子 int mid=(r+l)>>1; build(l,mid,p<<1); build(mid+1,r,p<<1|1); pushUp(p); } //区间查询 //线段树的最高顶点是表示所有行里面最大的宽度 int query(int l,int r,int p,int num) { if(l==r)//找到了一个完全重合的区间 { sum[p]-=num;//进行对应的查询操作 return l; } int ans; int mid=(r+l)>>1;//下面要注意,先保存ans,然后更新值后再返回 if(sum[p<<1]>=num) { ans=query(l,mid,p<<1,num); } else { ans=query(mid+1,r,p<<1|1,num); } pushUp(p); return 4000 ans; } int main() { while(scanf("%d%d%d",&h,&w,&n)!=EOF) { memset(sum,0,sizeof(sum)); if(h>n)h=n; int temp; build(1,h,1);//建树区间为[1,h],下标开始序号为1 for(int i=0;i<n;i++) { scanf("%d",&temp); if(sum[1]<temp) cout<<"-1"<<endl; else cout<<query(1,h,1,temp)<<endl; } } return 0; }
三、单点更新+区间求和
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define MAXN 50010 #define lson l,mid,p<<1 #define rson mid+1,r,p<<1|1 #define mem(a) memset(a,0,sizeof(a[0])) int sum[MAXN<<2]; void pushUp(int p) { sum[p]=sum[p<<1]+sum[p<<1|1]; } void build(int l,int r,int p) { if(l==r){ scanf("%d",&sum[p]); return; } int mid=(l+r)>>1; build(lson); build(rson); pushUp(p); } int query(int l,int r,int p,int i,int j) { if(l>=i&&r<=j){ return sum[p]; } int ans=0; int mid=(l+r)>>1; if(mid<j) ans+=query(rson,i,j); if(mid>=i) ans+=query(lson,i,j); return ans; } void update(int l,int r,int p,int i,int j) { if(l==r){ sum[p]+=j; return ; } int mid=(l+r)>>1; if(mid>=i) update(lson,i,j); else update(rson,i,j); pushUp(p); } int main() { int n,T; int cases=1; char str[10]; //freopen("in.txt","r",stdin); scanf("%d",&T); while(T--) { mem(sum); scanf("%d",&n); printf("Case %d:\n",cases++); int i,j; build(1,n,1); while(scanf("%s",str)&&strcmp(str,"End")) { scanf("%d%d",&i,&j); if(strcmp(str,"Query")==0) printf("%d\n",query(1,n,1,i,j)); else if(strcmp(str,"Add")==0) update(1,n,1,i,j); else if(strcmp(str,"Sub")==0) update(1,n,1,i,-j); } } return 0; }
四、区间查询最值+单点更新
#include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define MAXN 200010 #define lson l,mid,p<<1 #define rson mid+1,r,p<<1|1 int sum[MAXN<<2]; void pushUp(int p) { sum[p]=max(sum[p<<1],sum[p<<1|1]); } void build(int l,int r,int p) { if(l==r){ scanf("%d",&sum[p]); return ; } int mid=(l+r)>>1; build(lson); build(rson); pushUp(p); } int query(int l,int r,int p,int a,int b) { if(l>=a&&b>=r) return sum[p]; int ans=0; int mid=(l+r)>>1; if(mid>=a) ans=max(ans,query(lson,a,b)); if(mid<b) ans=max(ans,query(rson,a,b)); return ans; } void update(int l,int r,int p,int a,int b) { if(l==r){ sum[p]=b; return ; } int mid=(l+r)>>1; if(a<=mid) update(lson,a,b); else update(rson,a,b); pushUp(p); } int main() { int n,m; char ch[5]; //freopen("in.txt","r",stdin); while(~scanf("%d%d",&n,&m)) { int a,b; build(1,n,1); while(m--) { scanf("%s%d%d",ch,&a,&b); if(ch[0]=='Q') printf("%d\n",query(1,n,1,a,b)); else update(1,n,1,a,b); } } return 0; }
相关文章推荐
- hiho一下 第二十周(线段树模板)
- HDU 1754 I Hate it (线段树最大值模板)
- ACM模板——各种各样的线段树
- 线段树模板
- Hihocoder #1077 : RMQ问题再临-线段树(线段树:结构体建树+更新叶子往上+查询+巧妙使用father[]+线段树数组要开大4倍 *【模板】)
- cd 915E(离散化+线段树)(新线段树模板)
- 线段树模板
- 线段树最基本的模板
- 树状数组 线段树 模板
- 点更新线段树模板
- 【南阳OJ 116】士兵杀敌(二)(线段树)(更改某一点的值&查找总和 模板题)
- 【线段树模板】
- 线段树模板
- 模板:线段树(1)点修改
- 4000 HDU 4819 Mosaic(二维线段树区间查询+单点更新模板)
- 【模板】 递归线段树 [2017年五月计划 清北学堂51精英班Day4]
- POJ 2155 Matrix 【二维线段树模板题】
- 【模板】线段树 2
- 线段树模板
- HDU 1754 B I Hate It 线段树 单点更新 区间最大值 模板