1. 程式人生 > >線段樹||BZOJ1593: [Usaco2008 Feb]Hotel 旅館||Luogu P2894 [USACO08FEB]酒店Hotel

線段樹||BZOJ1593: [Usaco2008 Feb]Hotel 旅館||Luogu P2894 [USACO08FEB]酒店Hotel

旅館 font code truct getch ref www. 輸出 cst

題面:P2894 [USACO08FEB]酒店Hotel

題解:和基礎的線段樹操作差別不是很大,就是在傳統的線段樹基礎上多維護一段區間最長的合法前驅(h_),最長合法後驅(t_),一段中最長的合法區間(mx)。詢問時由於查詢的是最左邊的合法端點,所以要從左到中間到右邊依次考慮情況。

代碼:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<iostream>
 4 #define max(a,b) ((a)>(b)?(a):(b))
 5 using namespace std;
 6 const
int maxn=50000+5,maxm=50000+5; 7 int N,M,o,D,X,ans; 8 inline int rd(){ 9 int x=0;char c=getchar(); 10 while(c<0||c>9)c=getchar(); 11 while(c>=0&&c<=9){x=x*10+c-0;c=getchar();} 12 return x; 13 } 14 struct Tree{ 15 int l,r,lazy,h_,t_,mx; 16 }t[maxn<<2]; 17
inline void Pushup(int x){ 18 int ls=x<<1,rs=x<<1|1; 19 if(t[ls].r-t[ls].l+1==t[ls].mx)t[x].h_=t[ls].mx+t[rs].h_;else t[x].h_=t[ls].h_; 20 if(t[rs].r-t[rs].l+1==t[rs].mx)t[x].t_=t[rs].mx+t[ls].t_;else t[x].t_=t[rs].t_; 21 t[x].mx=max(t[ls].mx,t[rs].mx); 22 t[x].mx=max(t[x].mx,t[ls].t_+t[rs].h_);
23 return; 24 } 25 inline void Build(int x,int l,int r){ 26 t[x].l=l;t[x].r=r;t[x].lazy=-1; 27 if(l==r){ 28 t[x].h_=t[x].t_=t[x].mx=1; 29 return; 30 } 31 int mid=(l+r)>>1; 32 Build(x<<1,l,mid);Build(x<<1|1,mid+1,r); 33 Pushup(x); 34 return; 35 } 36 inline void Pushdown(int x){ 37 if(t[x].lazy>=0){ 38 int k=t[x].lazy,ls=x<<1,rs=x<<1|1;t[x].lazy=-1; 39 if(k==1){ 40 t[ls].h_=t[ls].t_=t[ls].mx=0; 41 t[rs].h_=t[rs].t_=t[rs].mx=0; 42 } 43 else{ 44 t[ls].h_=t[ls].t_=t[ls].mx=t[ls].r-t[ls].l+1; 45 t[rs].h_=t[rs].t_=t[rs].mx=t[rs].r-t[rs].l+1; 46 } 47 t[ls].lazy=t[rs].lazy=k; 48 } 49 return; 50 } 51 inline int Solve(int x,int d){ 52 int ls=x<<1,rs=x<<1|1,l=t[x].l,r=t[x].r; 53 if(r-l+1==t[x].mx&&t[x].mx==d)return l; 54 Pushdown(x); 55 if(t[ls].mx>=d)return Solve(ls,d); 56 if(t[ls].t_+t[rs].h_>=d)return (t[ls].r-t[ls].t_+1); 57 if(t[rs].mx>=d)return Solve(rs,d); 58 return 0; 59 } 60 inline void Update(int x,int ql,int qr,int o){ 61 int l=t[x].l,r=t[x].r; 62 if(ql<=l&&r<=qr){ 63 if(o==1)t[x].h_=t[x].t_=t[x].mx=0; 64 else t[x].h_=t[x].t_=t[x].mx=r-l+1; 65 t[x].lazy=o; 66 return; 67 } 68 int mid=(l+r)>>1,ls=x<<1,rs=x<<1|1; 69 Pushdown(x); 70 if(ql<=mid)Update(ls,ql,qr,o); 71 if(qr>mid)Update(rs,ql,qr,o); 72 Pushup(x); 73 return; 74 } 75 inline void write(int x){ 76 char a[12];int len=0; 77 for(;x;x/=10)a[len++]=x%10; 78 if(!len)putchar(0); 79 else while(len)putchar(a[--len]+0); 80 putchar(\n); 81 } 82 int main(){ 83 N=rd();M=rd(); 84 Build(1,1,N); 85 while(M--){ 86 o=rd(); 87 if(o==1){ 88 D=rd(); 89 ans=Solve(1,D); 90 write(ans); 91 if(ans)Update(1,ans,ans+D-1,1);//1表示有住人 92 } 93 else{ 94 X=rd();D=rd(); 95 Update(1,X,X+D-1,0); 96 } 97 } 98 return 0; 99 }

//我為了卡常加入了快速讀入和快速輸出,實際食用代碼時完全可以無視。


By:AlenaNuna

線段樹||BZOJ1593: [Usaco2008 Feb]Hotel 旅館||Luogu P2894 [USACO08FEB]酒店Hotel