线段树——简单篇
对节点进行操作
(1)hdu 1166 敌兵布阵
这是简单的练手题
View Code
#include <stdio.h> #include <stdlib.h> #include <string.h> #define size 50010 int sum[size<<2]; void PushUp(int rt) { int ls,rs; ls=rt<<1;rs=rt<<1|1; sum[rt]=sum[ls]+sum[rs]; } void build_tree(int l,int r,int rt) { int m=(l+r)>>1; sum[rt]=0; if(l==r) { scanf("%d",&sum[rt]); return ; } build_tree(l,m,rt<<1); build_tree(m+1,r,rt<<1|1); PushUp(rt); } int query(int L,int R,int l,int r,int rt) { int m=(l+r)>>1,res=0; if(L<=l&&r<=R) return sum[rt]; if(L<=m) res+=query(L,R,l,m,rt<<1); if(R>m) res+=query(L,R,m+1,r,rt<<1|1); return res; // PushUp(rt); } void inpoint(int num,int goal,int l,int r,int rt) { int m=(l+r)>>1; if(l==r) { sum[rt]+=num; return ; } if(goal<=m) inpoint(num,goal,l,m,rt<<1); if(goal>m) inpoint(num,goal,m+1,r,rt<<1|1); PushUp(rt); } int main() { int i,t,n,a,b; char str[10]; //freopen("test","r",stdin); scanf("%d",&t); for(i=1;i<=t;i++) { printf("Case %d:\n",i); scanf("%d",&n); build_tree(1,n,1); while(scanf("%s",str)) { if(strcmp(str,"End")==0) break; scanf("%d %d",&a,&b); if(strcmp(str,"Query")==0) { printf("%d\n",query(a,b,1,n,1)); } else if(strcmp(str,"Add")==0) inpoint(b,a,1,n,1); else if(strcmp(str,"Sub")==0) inpoint(-b,a,1,n,1); } } return 0; }
( 2 ) hdu 1754 I Hate It
也是一道水题,维护的最大值
View Code
#include <stdio.h> #include <stdlib.h> #include <string.h> #define size 200010 #define INF 1000000 #define max(a,b) (a)>(b)?(a):(b) int sum[size<<2]; void Pushup(int rt) { sum[rt]=max(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=(l+r)>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); Pushup(rt); } int query(int li,int ri,int l,int r,int rt) { int m=(l+r)>>1; int res1=-INF,res2=-INF; if(l>=li && r<=ri) return sum[rt]; if(li<=m) res1=query(li,ri,l,m,rt<<1); if(ri>m) res2=query(li,ri,m+1,r,rt<<1|1); return max(res1,res2); } void change(int goal,int num,int l,int r,int rt) { int m=(l+r)>>1; if(l==r) { sum[rt]=num; return ; } if(goal<=m) change(goal,num,l,m,rt<<1); else change(goal,num,m+1,r,rt<<1|1); Pushup(rt); } int main() { int n,m,i,a,b; char s[3]; // freopen("test","r",stdin); while(scanf("%d%d",&n,&m)!=EOF) { build(1,n,1); for(i=0;i<m;i++) { scanf("%s%d%d",s,&a,&b); if(s[0]=='Q') printf("%d\n",query(a,b,1,n,1)); else change(a,b,1,n,1); } } return 0; }
线段树最低层的节点一共有h个,每个大小是w,当贴上海报,减去海报的长,维护最大的点就OK了
View Code
#include<stdio.h> #include<string.h> #define size 200005 struct node { int l,r,m; }; node tree[size<<2]; int a; int h,w,n; void pushup(int rt) { if( tree[rt<<1].m>=tree[rt<<1|1].m) tree[rt].m=tree[rt<<1].m; else tree[rt].m=tree[rt<<1|1].m; } void build(int l,int r,int rt) { tree[rt].l=l; tree[rt].r=r; tree[rt].m=w; if(l==r) return ; int mid=(l+r)>>1; build(l,mid,rt<<1); build(mid+1,r,rt<<1|1); } void query(int num,int rt) { if(tree[rt].l==tree[rt].r) { tree[rt].m-=num; printf("%d\n",tree[rt].l); return ; } if(tree[rt<<1].m>=num) query(num,rt<<1); else query(num,rt<<1|1); pushup(rt); } int main() { while(scanf("%d%d%d",&h,&w,&n)!=EOF) { if(h>n) h=n; build(1,h,1); for(int i=0;i<n;i++) { scanf("%d",&a); if(tree[1].m<a) printf("-1\n"); else query(a,1); } } return 0; }
注意:倒叙,插入的位子是空格数,维护的是空格数的个数。
View Code
#include<cstdio> #include<string> #define size 200005 struct node { int l,r; int blank; }; node tree[size<<2]; struct point{ int po,va; }; point num[size]; int ans[size]; void pushup(int rt) { tree[rt].blank=tree[rt<<1].blank+tree[rt<<1|1].blank; } void build(int l,int r,int rt) { tree[rt].l=l; tree[rt].r=r; if(l==r) { tree[rt].blank=1; return ; } int m=(l+r)>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); pushup(rt); } void insert(int b,int va,int rt) { if(tree[rt].l==tree[rt].r) { tree[rt].blank--; ans[tree[rt].l]=va; return ; } if(tree[rt<<1].blank>=b) insert(b,va,rt<<1); else insert(b-tree[rt<<1].blank,va,rt<<1|1); pushup(rt); } int main() { int n,i; // freopen("test","r",stdin); while(scanf("%d",&n)!=EOF) { build(1,n,1); for(i=1;i<=n;i++) scanf("%d%d",&num[i].po,&num[i].va); for(i=n;i>0;i--) insert(num[i].po+1,num[i].va,1); for(i=1;i<=n;i++) { if(i!=1) printf(" "); printf("%d",ans[i]); } printf("\n"); } return 0; }
对段进行更新
注意lazy数组的使用;
View Code
#include<cstdio> #include<string> #define size 100005 struct node { int l,r; int sum; int lazy; }; node tree[size<<2]; int ans[size]; void pushup(int rt) { tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum; } void pushdown(int rt) { tree[rt<<1].lazy=tree[rt].lazy; tree[rt<<1|1].lazy=tree[rt].lazy; tree[rt<<1].sum=(tree[rt<<1].r-tree[rt<<1].l+1)*tree[rt].lazy; tree[rt<<1|1].sum=(tree[rt<<1|1].r-tree[rt<<1|1].l+1)*tree[rt].lazy; tree[rt].lazy=0; } void build(int l,int r,int rt) { tree[rt].l=l; tree[rt].r=r; tree[rt].sum=1; tree[rt].lazy=0; if(l==r) return ; int m=(l+r)>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); pushup(rt); } void change(int l,int r,int z,int rt) { if(tree[rt].l==l && tree[rt].r==r) { tree[rt].lazy=z; tree[rt].sum=(r-l+1)*z; return ; } if(tree[rt].lazy!=0) pushdown(rt); int m=(tree[rt].l+tree[rt].r)>>1; if(m>=r) change(l,r,z,rt<<1); else if(m<l) change(l,r,z,rt<<1|1); else { change(l,m,z,rt<<1); change(m+1,r,z,rt<<1|1); } pushup(rt); } int main() { int n,i,t,q; int l,r,z; freopen("test","r",stdin); scanf("%d",&t); for(int as=1;as<=t;as++) { scanf("%d%d",&n,&q); build(1,n,1); for(i=0;i<q;i++) { scanf("%d%d%d",&l,&r,&z); change(l,r,z,1); } printf("Case %d: The total value of the hook is %d.\n",as,tree[1].sum); } return 0; }
(2)poj3468 A Simple Problem with Integers
题很简单,但是要注意:输入输出,会发生溢出
View Code
#include<cstdio> #include<string> #define size 100005 struct node { int l,r; __int64 sum; __int64 lazy; }; node tree[size<<2];; void pushup(int rt) { tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum; } void pushdown(int rt) { tree[rt<<1].lazy+=tree[rt].lazy; tree[rt<<1|1].lazy+=tree[rt].lazy; tree[rt<<1].sum+=(tree[rt<<1].r-tree[rt<<1].l+1)*tree[rt].lazy; tree[rt<<1|1].sum+=(tree[rt<<1|1].r-tree[rt<<1|1].l+1)*tree[rt].lazy; tree[rt].lazy=0; } void build(int l,int r,int rt) { tree[rt].l=l; tree[rt].r=r; tree[rt].sum=0; tree[rt].lazy=0; if(l==r) { scanf("%I64d",&tree[rt].sum); return ; } int m=(l+r)>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); pushup(rt); } void change(int l,int r,int z,int rt) { if(tree[rt].l==l && tree[rt].r==r) { tree[rt].lazy+=z; tree[rt].sum+=(r-l+1)*z; return ; } if(tree[rt].lazy!=0) pushdown(rt); int m=(tree[rt].l+tree[rt].r)>>1; if(m>=r) change(l,r,z,rt<<1); else if(m<l) change(l,r,z,rt<<1|1); else { change(l,m,z,rt<<1); change(m+1,r,z,rt<<1|1); } pushup(rt); } __int64 query(int l,int r,int rt) { if(tree[rt].l==l && tree[rt].r==r) { return tree[rt].sum; } if(tree[rt].lazy!=0) pushdown(rt); int m=(tree[rt].l+tree[rt].r)>>1; if(m>=r) return query(l,r,rt<<1); else if(m<l) return query(l,r,rt<<1|1); else return query(l,m,rt<<1)+query(m+1,r,rt<<1|1); } int main() { int i,n,q; int l,r,z; char s[3]; // freopen("test","r",stdin); scanf("%d%d",&n,&q); build(1,n,1); for(i=0;i<q;i++) { scanf("%s",&s); if(s[0]=='Q') { scanf("%d%d",&l,&r); printf("%I64d\n",query(l,r,1)); } else { scanf("%d%d%d",&l,&r,&z); change(l,r,z,1); } } return 0; }
主要是离散化,这是一个重点,为自己确定一个模板,以后可以接着用。
还有 在最大的范围要注意。
View Code
#include<cstdio> #include<cstring> #include<algorithm> #define size 40005 using namespace std; struct node { int l,r; int sum; int lazy; }; node tree[size<<2];; int point[size]; int vis[size],ans; void pushup(int rt) { if(tree[rt<<1].sum==tree[rt<<1|1].sum) tree[rt].sum=tree[rt<<1].sum; else tree[rt].sum=-1; } void pushdown(int rt) { tree[rt<<1].lazy=tree[rt].lazy; tree[rt<<1|1].lazy=tree[rt].lazy; tree[rt<<1].sum=tree[rt].sum; tree[rt<<1|1].sum=tree[rt].sum; tree[rt].lazy=0; } void build(int l,int r,int rt) { tree[rt].l=l; tree[rt].r=r; tree[rt].sum=0; tree[rt].lazy=0; if(l==r) return ; int m=(l+r)>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); } void change(int l,int r,int rt,int i) { if(tree[rt].l==l && tree[rt].r==r) { tree[rt].lazy=1; tree[rt].sum=i; return ; } if(tree[rt].lazy!=0) pushdown(rt); int m=(tree[rt].l+tree[rt].r)>>1; if(m>=r) change(l,r,rt<<1,i); else if(m<l) change(l,r,rt<<1|1,i); else { change(l,m,rt<<1,i); change(m+1,r,rt<<1|1,i); } pushup(rt); } void query(int rt) { if(tree[rt].sum==0) return; if(tree[rt].sum!=-1) { if(vis[tree[rt].sum]==0) { vis[tree[rt].sum]=1; ans++; return; } return; } if(tree[rt].lazy!=0) pushdown(rt); query(rt<<1); query(rt<<1|1); } int find(int key,int n) { int l = 0 , r = n - 1; while (l <= r) { int m = (l + r) >> 1; if (point[m] == key) return m; if (point[m] < key) l = m + 1; else r = m - 1; } return -1; } int main() { int i,n,t,li,ri; int l[size],r[size]; // freopen("test","r",stdin); scanf("%d",&t); while(t--) { scanf("%d",&n); int nn=0; for(i=0;i<n;i++) { scanf("%d%d",&l[i],&r[i]); point[nn++]=l[i]; point[nn++]=r[i]; } sort(point , point + nn); int m = 1; for (i = 1 ; i < nn; i ++) { if (point[i] != point[i-1]) point[m ++] = point[i]; } for (i = m - 1 ; i > 0 ; i --) { if (point[i] != point[i-1] + 1) point[m ++] = point[i-1] + 1; } sort(point , point + m); build(0,m-1,1); memset(vis,0,sizeof(vis)); ans=0; for(i=0;i<n;i++) { li=find(l[i],m); ri=find(r[i],m); // printf("%d %d\n",li,ri); change(li,ri,1,i+1); } query(1); printf("%d\n",ans); } return 0; }


浙公网安备 33010602011771号