线段树单点更新

来源:互联网 发布:巨鹰飞行网络 编辑:程序博客网 时间:2024/05/18 06:24

HDU 1166

http://acm.hdu.edu.cn/showproblem.php?pid=1166

单点更新,求区间和


第一次写线段树,照着大神的抄了一遍

#include <iostream>#include <cstdio>#include <cstring>#define MAX 50100#define mid (l+r)>>1#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;int sum[MAX<<2];void pushup(int rt){sum[rt]=sum[rt<<1]+sum[rt<<1|1];}void build(int l,int r,int rt){if(l==r){scanf("%d",&sum[rt]);return;}int m=mid;build(lson);build(rson);pushup(rt);}void Updata(int s,int add,int l,int r,int rt){if(l==r){sum[rt]+=add;return;}int m=mid;if(s<=m) Updata(s,add,lson);else Updata(s,add,rson);pushup(rt);}int query(int L,int R,int l,int r,int rt){if(L<=l && R>=r){return sum[rt];}int m=mid;int ret=0;if(L<=m) ret+=query(L,R,lson);if(R>m)  ret+=query(L,R,rson);return ret;}int main(){int t,flag=0,n;scanf("%d",&t);while(t--){++flag;printf("Case %d:\n",flag);scanf("%d",&n);build(1,n,1);char ch[20];while(scanf("%s",ch)!=EOF){if(ch[0]=='E') break;int a,b;scanf("%d%d",&a,&b);if(ch[0]=='A') Updata(a,b,1,n,1);else if(ch[0]=='S') Updata(a,-b,1,n,1);else {printf("%d\n",query(a,b,1,n,1));}}}return 0;}


hdu 1754 i hate it

http://acm.hdu.edu.cn/showproblem.php?pid=1754

单点更新,求区间最值

#include <iostream>#include <cstdio>#include <cstring>#define MAX 200100#define mid (l+r)>>1#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1using namespace std;int num[MAX<<2];int n,m;int max(int a,int b){if(a>b) return a;return b;}void build(int l,int r,int rt){if(l==r){scanf("%d",&num[rt]);return;}int m=mid;build(lson);build(rson);num[rt]=max(num[rt<<1],num[rt<<1|1]);}int query(int L,int R,int l,int r,int rt){if(L<=l && R>=r){return num[rt];}int m=mid;int ret=-0x3f3f3f3f;if(L<=m)  ret=max(ret,query(L,R,lson));if(R>m)   ret=max(ret,query(L,R,rson));return ret;}void Updata(int p,int add,int l,int r,int rt){if(l==r){num[rt]=add;return;}int m=mid;if(p<=m) Updata(p,add,lson);else Updata(p,add,rson);num[rt]=max(num[rt<<1],num[rt<<1|1]);}int main(){while(scanf("%d%d",&n,&m)!=EOF){build(1,n,1);char ch[2];int a,b;for(int i=1; i<=m; i++){scanf("%s%d%d",ch,&a,&b);if(ch[0]=='Q') printf("%d\n",query(a,b,1,n,1));else Updata(a,b,1,n,1);}}return 0;}

POJ  2828 

http://poj.org/problem?id=2828

向序列内部插入数字,求最后的序列

#include <iostream>#include <cstring>#include <cstdio>#define MAX  200100#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define mid (l+r)>>1using namespace std;int num[MAX<<2],n;int pos[MAX],value[MAX];int id;int ans[MAX];void build(int l,int r,int rt){num[rt]=(r-l)+1;         //子树有多少个空位if(l==r){return;}int m=mid;build(lson);build(rson);}void Updata(int p,int l,int r,int rt){num[rt]--;          //向子树中插入的话,子树空位-1if(l==r){id=l;return;}int m=mid;if(num[rt<<1]>=p) Updata(p,lson);       //当左子树有充足空位时,插在左子树else{p-=num[rt<<1];                   //当左子树不充足时,插在右子树,在插入之前要减去左子树中含有的空位数Updata(p,rson);}}int main(){while(scanf("%d",&n)!=EOF){build(1,n,1);for(int i=1; i<=n; i++){scanf("%d%d",&pos[i],&value[i]);}for(int i=n; i>=1; i--){Updata(pos[i]+1,1,n,1);ans[id]=value[i];}for(int i=1; i<=n; i++){printf(i!=n?"%d ":"%d\n",ans[i]);}}return 0;}

HDU 1556

http://acm.hdu.edu.cn/showproblem.php?pid=1556

每次更新只需要更新到子树的根节点,然后在最后求的时候从根节点加到叶节点,即为叶节点被染色的次数


#include <iostream>#include <cstdio>#include <cstring>using namespace std;#define MAX 100100#define mid (l+r)>>1#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int num[MAX<<2];int n;void Updata(int L,int R,int l,int r,int rt){if(L<=l && R>=r){num[rt]++;return;}int m=mid;if(L<=m) Updata(L,R,lson);if(R>m) Updata(L,R,rson);}void query(int l,int r,int rt,int sum){if(l==r){printf(l!=n?"%d ":"%d\n",sum+num[rt]);return;}int m=mid;sum+=num[rt];query(lson,sum);query(rson,sum);}int main(){while(scanf("%d",&n) && n){int a,b;memset(num,0,sizeof(num));for(int i=1; i<=n; i++){scanf("%d%d",&a,&b);Updata(a,b,1,n,1);}query(1,n,1,0);}return 0;}


 

原创粉丝点击