POJ 3667 Hotel 模擬+暴力
阿新 • • 發佈:2018-11-19
/** POJ 3667 Hotel 模擬+暴力 連結:http://poj.org/problem?id=3667 題意:給定長度為n初始化值為0的陣列a,每次詢問存在兩個操作; 1 x : 新添進來值為1,大小長度為x的陣列b.每次新添進去的位置為:最左邊,且能全部一次性放下的地點 也就是最左邊連續0的個數的長度得大於等於x,輸出當前賦值的起始點; 2 x d: 以x為起點長度為d的後面位置全部清為0; 分析:可用vector進行模擬,存取節點,節點表示1-->n值為0的區間,維護一個單調的vector; 對於詢問操作,直接暴力vec進行遍歷即可,並注意當前滿足條件的區間變化; 對於區間推平操作,找到最右邊的點的位置,對於左端點到當前最右的點,進行刪除,即可完成區間推平操作 也就是將多個不為0的區間化為一個區間的過程; */ #include<vector> #include<iostream> #include<algorithm> #include<cstdio> #include<cmath> #define ll long long using namespace std; int n,q; struct node { int l,r; }; vector<node>vec; int main(){ scanf("%d %d",&n,&q); node tmp;tmp.l=1,tmp.r=n; vec.push_back(tmp); while(q--){ int cas;scanf("%d",&cas); if(cas==1) { int x;scanf("%d",&x); int id=0,sz=vec.size();//至少存在一個,留; //for(int i=0;i<sz-1;i++) if((vec[i].r-vec[i].l+1)>=x) { id=i;break;} while((vec[id].r-vec[id].l+1)<x&&id<vec.size()-1) id++;//保證vec不能為空 方便下面的判斷; if((vec[id].r-vec[id].l+1)>=x){ printf("%d\n",vec[id].l); vec[id].l+=x; if(vec[id].l>vec[id].r) vec.erase(vec.begin()+id); } else puts("0"); } else { int x,d;scanf("%d %d",&x,&d); d=x+d-1; node tmp;tmp.l=x,tmp.r=d; if(vec.size()==0) vec.push_back(tmp);//全是滿的情況; else if(vec.size()==1){ if(vec[0].l-1>d) vec.insert(vec.begin(),1,tmp);//記得維護vec的區間單調性(遞增); else if(vec[0].r<x-1) vec.push_back(tmp); else vec[0].l=min(vec[0].l,x),vec[0].r=max(vec[0].r,d); } else if(vec.size()>1){ int id=0,sz=vec.size(); //for(int i=0;i<sz-1;i++) if(vec[i].r+1>=x) { id=i; break; } while((vec[id].r+1)<x&&id<vec.size()-1) id++; if(vec[id].l-1>d) vec.insert(vec.begin()+id,1,tmp); else if(vec[id].r<x-1) vec.push_back(tmp); else { vec[id].l=min(vec[id].l,x),vec[id].r=max(vec[id].r,d); for(int i=id;i<vec.size()-1;){ if(vec[i+1].l-1>vec[i].r) break; vec[i].r=max(vec[i].r,vec[i+1].r); vec.erase(vec.begin()+i+1); } } } } } return 0; } /** 10 6 1 4 1 4 2 2 5 */