Bzoj 3050: [Usaco2013 Jan]Seating(线段树裸题,然而区间修改标记下放和讨论Push_up很揪心)
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Bzoj 3050: [Usaco2013 Jan]Seating(线段树裸题,然而区间修改标记下放和讨论Push_up很揪心)相关的知识,希望对你有一定的参考价值。
题目链接题意:开始有一个空白的区间,每次可能进行两个操作:A 将一个长度为p的区间加入一段连续空白的位置 L:一个区间恢复空白;要求出A不能进行的次数。
非常裸的线段树题目,用线段树统计最大的空白区间,每个节点需要记录当前区间的最长空白区间,从左端开始的最长空白区间,从右端开始的最长空白区间。Push_up的时候要讨论下,可以分别取[l,mid]和[mid+1,r]的最大空白区间,也可以用[l,mid]的从右端开始的最长空白区间+[mid+1,r]从左端开始的最大空白区间。
每次A的时候,就查询一下当前能装下p的空白区间中最靠左的位置(用一个全局变量ans统计下),如果根节点的最长空白区间>=p,就把[ans,ans+p-1]变成被占有的状态,否则就在答案中++;如果是L,那就更简单,直接区间修改(听说不打标记能得的分比我这个考场未调试直接爆0的分高?)。标记的下方都是基本功了(一定是当前节点已经修改而子区间未修改)。
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #define l i<<1 5 #define r i<<1|1 6 #define mid (x+y)/2 7 #define lson x,mid 8 #define rson mid+1,y 9 using namespace std; 10 const int inf=0x7fffffff; 11 const int N=500005; 12 struct hp{int w,p,li,ri,size,delta;}a[N<<2]; 13 int ans; 14 inline int in() 15 { int x=0; char ch=getchar(); while (ch<‘0‘||ch>‘9‘) ch=getchar(); 16 while (ch>=‘0‘&&ch<=‘9‘) x=x*10+ch-‘0‘,ch=getchar();return x;} 17 inline int get(){char ch=getchar();while (ch!=‘A‘&&ch!=‘L‘) ch=getchar();return ch==‘A‘;} 18 void build(int i,int x,int y) 19 { a[i]=(hp){y-x+1,x,y-x+1,y-x+1,y-x+1,-1}; 20 if (x==y) return;build(l,lson); build(r,rson); 21 } 22 void pushdown(int i,int x,int y) 23 { int c=a[i].delta; a[i].delta=-1;a[l].delta=a[r].delta=c; 24 if (c){a[l].w=a[l].li=a[l].ri=0,a[l].p=inf;a[r].w=a[r].li=a[r].ri=0,a[r].p=inf;} 25 else{a[l].w=a[l].li=a[l].ri=mid-x+1,a[l].p=x;a[r].w=a[r].li=a[r].ri=y-mid,a[r].p=mid+1;} 26 } 27 inline hp updata(hp A,hp B,int x,int y) 28 { hp c; c.delta=-1;c.size=A.size+B.size; 29 if (!A.w) c.w=B.w,c.li=0,c.ri=B.ri,c.p=B.p; 30 else if (!B.w) c.w=A.w,c.li=A.li,c.ri=0,c.p=A.p; 31 else{ c.li=A.li+(A.li==A.size?B.li:0); 32 c.ri=B.ri+(B.ri==B.size?A.ri:0); 33 if (A.w>=B.w) c.w=A.w,c.p=A.p; 34 else c.w=B.w,c.p=B.p; 35 if (A.ri+B.li>c.w||(A.ri+B.li==c.w&&mid-A.ri+1<c.p)) 36 c.w=A.ri+B.li,c.p=mid-A.ri+1; 37 }return c; 38 } 39 void insert(int i,int x,int y,int s,int t,int k) 40 { if (x>=s&&y<=t) 41 { if (k) a[i]=(hp){0,inf,0,0,y-x+1,1}; 42 else a[i]=(hp){y-x+1,x,y-x+1,y-x+1,y-x+1,0};return;} 43 if (a[i].delta!=-1) pushdown(i,x,y); 44 if (s<=mid) insert(l,lson,s,t,k);if (t>mid) insert(r,rson,s,t,k); 45 a[i]=updata(a[l],a[r],x,y); 46 } 47 void query(int i,int x,int y,int k){ 48 if (x==y){ans=x; return;} 49 if (a[i].delta!=-1) pushdown(i,x,y); 50 if (a[l].w>=k) query(l,lson,k); 51 else if (a[l].ri+a[r].li>=k){ 52 ans=mid-a[l].ri+1; 53 return; 54 }else query(r,rson,k); 55 } 56 int main() 57 { int n=in(),m=in(); 58 build(1,1,n); int tot=0; 59 while (m--) 60 { int opt=get(); 61 if (opt) 62 { int x=in();if (!x) continue; 63 if (a[1].w<x) tot++; 64 else { query(1,1,n,x); 65 insert(1,1,n,ans,ans+x-1,1); 66 }} 67 else{ int x=in(),y=in();insert(1,1,n,x,y,0);} 68 69 } 70 cout<<tot<<endl; 71 }
调试能力有待提升。
以上是关于Bzoj 3050: [Usaco2013 Jan]Seating(线段树裸题,然而区间修改标记下放和讨论Push_up很揪心)的主要内容,如果未能解决你的问题,请参考以下文章
[BZOJ 3048][Luogu P3069][USACO2013 Jan]Cow Lineup
[bzoj3048] [Usaco2013 Jan]Cow Lineup
bzoj 4506: [Usaco2016 Jan]Fort Moo
[BZOJ1677][Usaco2005 Jan]Sumsets 求和