本来这个题目就是个合并区间的题,就跟Hotel一样,要插入一段,则找左孩子 合并后的中间区间 右孩子,但是比较恶心的是,他需要实时得到某一段的起终点,或者某个点在第几个段里面,我想过在线段树里面加入几个变量来记录左右边界,发现还是不行,因为还要可以消除某个区间段
后来找博客发现向量原来还可以动态的插入和删除,那我把每一块的起终点放在向量里面,既能有序的进行查找,又能再Free操作的时候,直接马上把这个区间抹除,解决了这个问题,其他就跟Hotel区间查询 和 懒惰标记是一样的了,由于向量里面存储的是有序的,所以用二分进行查找
#include <iostream> #include <cstdio> #include <cstring> #include <vector> #define lson rt<<1,l,mid #define rson rt<<1|1,mid+1,r #define N 50010 using namespace std; typedef pair<int,int> pill; vector<pill> till; int mc[N*3],lc[N*3],rc[N*3],flag[N*3]; int n,m; int max(int a,int b) {return a>b? a:b;} void up(int rt,int l,int r) { int ll=rt<<1,rr=rt<<1|1; mc[rt]=max(mc[ll],mc[rr]); lc[rt]=lc[ll];rc[rt]=rc[rr]; int mid=(l+r)>>1; if (lc[rt]==mid-l+1) lc[rt]+=lc[rr]; if (rc[rt]==r-mid) rc[rt]+=rc[ll]; if (lc[rr]+rc[ll]>mc[rt]){ mc[rt]=lc[rr]+rc[ll]; } } void build(int rt,int l,int r) { flag[rt]=-1; if (l>=r){ mc[rt]=lc[rt]=rc[rt]=1; return; } int mid=(l+r)>>1; build(lson); build(rson); up(rt,l,r); } void pushdown(int rt,int l,int r){ if (flag[rt]==-1 || l>=r) return; int mid=(l+r)>>1; mc[rt<<1]=(mid-l+1)*flag[rt]; mc[rt<<1|1]=(r-mid)*flag[rt]; lc[rt<<1]=rc[rt<<1]=(mid-l+1)*flag[rt]; lc[rt<<1|1]=rc[rt<<1|1]=(r-mid)*flag[rt]; flag[rt<<1]=flag[rt<<1|1]=flag[rt]; flag[rt]=-1; } void cover(int L,int R,int rt,int l,int r,int rec){ int mid=(l+r)>>1; if (L<=l && r<=R){ flag[rt]=rec; mc[rt]=lc[rt]=rc[rt]=(r-l+1)*flag[rt]; return; } if (flag[rt]!=-1) pushdown(rt,l,r); if (L<=mid) cover(L,R,lson,rec); if (R>mid) cover(L,R,rson,rec); up(rt,l,r); } int query(int x,int rt,int l,int r) { pushdown(rt,l,r); if (l>=r) return l; int mid=(l+r)>>1; if (mc[rt<<1]>=x) return query(x,lson); if (lc[rt<<1|1]+rc[rt<<1]>=x) return mid-rc[rt<<1]+1; return query(x,rson); } int bs(int x) { int l=0,r=till.size()-1,mid; while (l<=r){ mid=(l+r)>>1; if (till[mid].first<=x) l=mid+1; else r=mid-1; } return l; } void solve(char* ch) { if (ch[0]=='R'){ till.clear(); cover(1,n,1,1,n,1); puts("Reset Now"); return; } int d; scanf("%d",&d); if (ch[0]=='N'){ if (mc[1]<d) {puts("Reject New");return;} int sta=query(d,1,1,n); printf("New at %d ",sta); int a=bs(sta); pill c;c.first=sta;c.second=sta+d-1; till.insert(till.begin()+a,c); cover(sta,sta+d-1,1,1,n,0); return; } if (ch[0]=='F'){ int id=bs(d); id--; if (id<=-1||till[id].second<d) puts("Reject Free"); else{ printf("Free from %d to %d ",till[id].first,till[id].second); cover(till[id].first,till[id].second,1,1,n,1); till.erase(till.begin()+id); } return; } if (ch[0]=='G') { if (d > till.size()) printf("Reject Get "); else printf("Get at %d ", till[d-1].first); } } int main() { char ch[8]; while (scanf("%d%d",&n,&m)!=EOF) { build(1,1,n); till.clear(); for (int q=0;q<m;q++){ scanf("%s",ch); solve(ch); } printf(" "); } return 0; }