线段树——提高篇
虽然线段树我没有学多久,但是我的格式被好几个人鄙弃,从今天开始,我要更改线段树的格式。
pushup( rt ) 向下更新lazy 等节点信息。
pushdown( rt ) 向上更新
活用 lazy 标志,
新的格式:
View Code
#include<stdio.h> #include<string.h> #include<math.h> int max(int a,int b) { return a>b?a:b; } int min(int a,int b) { return a<b?a:b; } const int size=10005; typedef struct node { int l,r; int exp,lev; int lazy; int mis_dis; }node; node tree[size*5]; int a[15],k; void pushdown(int rt) { int nl=rt<<1,nr=rt<<1|1; tree[nl].exp+=tree[rt].lazy*tree[nl].lev; tree[nl].lazy+=tree[rt].lazy; tree[nl].mis_dis-=tree[rt].lazy; tree[nr].exp+=tree[rt].lazy*tree[nr].lev; tree[nr].lazy+=tree[rt].lazy; tree[nr].mis_dis-=tree[rt].lazy; tree[rt].lazy=0; } void pushup(int rt) { tree[rt].exp=max(tree[rt<<1].exp,tree[rt<<1|1].exp); tree[rt].lev=max(tree[rt<<1].lev,tree[rt<<1|1].lev); tree[rt].mis_dis=min(tree[rt<<1].mis_dis,tree[rt<<1|1].mis_dis); } void build(int l,int r,int rt) { tree[rt].l=l; tree[rt].r=r; tree[rt].exp=0; tree[rt].lazy=0; tree[rt].lev=1; tree[rt].mis_dis=a[1]; if(l==r) return ; int m=(l+r)>>1; build(l,m,rt<<1); build(m+1,r,rt<<1|1); } void add(int l,int r,int e,int rt) { if(tree[rt].l==tree[rt].r) //更新叶子 { tree[rt].exp+=tree[rt].lev*e; while(tree[rt].exp>=a[tree[rt].lev]) tree[rt].lev++; tree[rt].mis_dis=(a[tree[rt].lev]-tree[rt].exp)/tree[rt].lev; if((a[tree[rt].lev]-tree[rt].exp)%tree[rt].lev) tree[rt].mis_dis++; return; } if(tree[rt].l==l && tree[rt].r==r) { if(e>=tree[rt].mis_dis) { if(tree[rt].lazy) pushdown(rt); add(tree[rt<<1].l,tree[rt<<1].r,e,rt<<1); add(tree[rt<<1|1].l,tree[rt<<1|1].r,e,rt<<1|1); pushup(rt); } else { tree[rt].exp+=tree[rt].lev*e; tree[rt].lazy+=e; tree[rt].mis_dis-=e; } return ; } if(tree[rt].lazy) pushdown(rt); int m=(tree[rt].l+tree[rt].r)>>1; if(m>=r) add(l,r,e,rt<<1); else if(m<l) add(l,r,e,rt<<1|1); else { add(l,m,e,rt<<1); add(m+1,r,e,rt<<1|1); } pushup(rt); } int query(int l,int r,int rt) { if(tree[rt].l==l && tree[rt].r==r) return tree[rt].exp; if(tree[rt].lazy) 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 max(query(l,m,rt<<1),query(m+1,r,rt<<1|1)); } int main() { int t,i; int n,qw,li,ri,ei; char str[5]; scanf("%d",&t); for(int as=1;as<=t;as++) { printf("Case %d:\n",as); scanf("%d%d%d",&n,&k,&qw); for( i=1;i<k;i++) scanf("%d",&a[i]); a[k]=1<<30; build(1,n,1); for(i=0;i<qw;i++) { scanf("%s%d%d",str,&li,&ri); if(str[0]=='W') { scanf("%d",&ei); add(li,ri,ei,1); } else { printf("%d\n",query(li,ri,1)); } } printf("\n"); } return 0; }
区间合并
基本的区间合并,主要是写时要细心就好。
View Code
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #define size 50005 5 using namespace std; 6 7 struct node 8 { 9 int l,r; 10 int ls,rs,m; 11 int lazy; 12 }tree[size<<2]; 13 14 void build(int l,int r,int rt) 15 { 16 tree[rt].l=l; 17 tree[rt].r=r; 18 tree[rt].ls=tree[rt].rs=tree[rt].m=r-l+1; 19 tree[rt].lazy=-1; 20 if(l==r) 21 return ; 22 int mid=(l+r)>>1; 23 build(l,mid,rt<<1); 24 build(mid+1,r,rt<<1|1); 25 } 26 void pushdown(int rt) 27 { 28 tree[rt<<1].lazy=tree[rt<<1|1].lazy=tree[rt].lazy; 29 tree[rt<<1].ls=tree[rt<<1].rs=tree[rt<<1].m=tree[rt].lazy?0:tree[rt<<1].r-tree[rt<<1].l+1; 30 tree[rt<<1|1].ls=tree[rt<<1|1].rs=tree[rt<<1|1].m=tree[rt].lazy?0:tree[rt<<1|1].r-tree[rt<<1|1].l+1; 31 tree[rt].lazy=-1; 32 } 33 void pushup(int rt) 34 { 35 tree[rt].ls=tree[rt<<1].ls; 36 tree[rt].rs=tree[rt<<1|1].rs; 37 if(tree[rt].ls==tree[rt<<1].r-tree[rt<<1].l+1) 38 tree[rt].ls+=tree[rt<<1|1].ls; 39 if(tree[rt].rs==tree[rt<<1|1].r-tree[rt<<1|1].l+1) 40 tree[rt].rs+=tree[rt<<1].rs; 41 tree[rt].m=max(max(tree[rt<<1].m,tree[rt<<1|1].m),tree[rt<<1].rs+tree[rt<<1|1].ls); 42 } 43 44 int query(int a,int rt) 45 { 46 if(tree[rt].l==tree[rt].r) 47 return tree[rt].l; 48 if(tree[rt].lazy!=-1) 49 pushdown(rt); 50 if(tree[rt<<1].m>=a) 51 return query(a,rt<<1); 52 else if(tree[rt<<1].rs+tree[rt<<1|1].ls>=a) 53 return tree[rt<<1].r-tree[rt<<1].rs+1; 54 else 55 return query(a,rt<<1|1); 56 } 57 58 void update(int li,int ri,int t,int rt) 59 { 60 if(tree[rt].l==li && tree[rt].r==ri) 61 { 62 tree[rt].lazy=t; 63 tree[rt].ls=tree[rt].rs=tree[rt].m=t?0:ri-li+1; 64 return ; 65 } 66 if(tree[rt].lazy!=-1) 67 pushdown(rt); 68 int mid=(tree[rt].l+tree[rt].r)>>1; 69 if(ri<=mid) 70 update(li,ri,t,rt<<1); 71 else if(li>mid) 72 update(li,ri,t,rt<<1|1); 73 else 74 { 75 update(li,mid,t,rt<<1); 76 update(mid+1,ri,t,rt<<1|1); 77 } 78 pushup(rt); 79 } 80 81 int main() 82 { 83 int n,m,i; 84 int flag,a,x; 85 scanf("%d%d",&n,&m); 86 build(1,n,1); 87 for(i=0;i<m;i++) 88 { 89 scanf("%d",&flag); 90 if(flag==1) 91 { 92 scanf("%d",&a); 93 if(tree[1].m<a) 94 printf("0\n"); 95 else 96 { 97 int ans=query(a,1); 98 printf("%d\n",ans); 99 update(ans,ans+a-1,1,1); 100 } 101 } 102 else 103 { 104 scanf("%d%d",&x,&a); 105 update(x,x+a-1,0,1); 106 } 107 } 108 return 0; 109 }
还有 :hdu 3308 LCIS (求区间内最长连续递增的个数 )(又增加乐两个变量,还有,注意query的操作)


浙公网安备 33010602011771号