hdu2871 Memory Control 线段树,二分

来源:互联网 发布:网络用户的未来发展 编辑:程序博客网 时间:2024/06/05 10:16

之前在poj做过hotel题,看到这题时就想到是线段树了。但是这题比hotel多一些操作,这就让我捉急了。这里NEW操作相当于hotel中的入住,Free操作相当于退房,但是又有一点不同,每次给你一个地址,要求知道这个地址是否在使用,在使用的话是被哪个区间使用,在这个操作中借用的别人的想法,利用vector二分查找位置,GET操作由于引用的vector所以操作很简单,在Reset操作时不能重新建树,否则会超时, 要用update进行更新。

#include <iostream>#include <cstdio>#include <algorithm>#include <vector>using namespace std;const int maxn = 50000+10;struct ST {      int l, r, lsum, rsum, sum, d;}v[maxn<<2];int n, m, data;char s[11];struct node {      int s, e;      node(int s, int e):s(s), e(e){}};bool cmp(const node &a, const node &b) {      return a.s<b.s;//按开始的位置排序}vector<node> vc;vector<node>::iterator it;void build(int l, int r, int n) {      v[n].l = l, v[n].r = r;      v[n].lsum = v[n].rsum = v[n].sum = r-l+1;      v[n].d = -1;      if (l==r)            return ;      int mid = (v[n].l + v[n].r) >> 1;      build (l, mid, n<<1);      build(mid+1, r, n<<1|1);}inline void pushdown(int n) {      if (v[n].d!=-1) {            v[n<<1].d = v[n<<1|1].d = v[n].d;            int len = (v[n].r-v[n].l+1);            v[n<<1].lsum = v[n<<1].rsum = v[n<<1].sum = v[n].d==1?0:(len-(len>>1));            v[n<<1|1].lsum = v[n<<1|1].rsum = v[n<<1|1].sum = v[n].d==1?0:(len>>1);            v[n].d = -1;      }}int query(int size, int n) {      if (v[n].l==v[n].r)            return v[n].l;      int mid = (v[n].l + v[n].r) >> 1;      pushdown(n);      if (v[n<<1].sum>=size) {            return  query(size, n<<1);      } else if (v[n<<1].rsum+v[n<<1|1].lsum>=size) {            return mid-v[n<<1].rsum+1;      } else {            return query(size, n<<1|1);      }}inline int Max(int x, int y) {      return x>y?x:y;}inline void pushup(int n) {      v[n].lsum = v[n<<1].lsum;      v[n].rsum = v[n<<1|1].rsum;      int len = (v[n].r-v[n].l+1);      if (v[n].lsum==(len-(len>>1)))            v[n].lsum += v[n<<1|1].lsum;      if (v[n].rsum==(len>>1))            v[n].rsum += v[n<<1].rsum;      v[n].sum = Max(v[n<<1].rsum+v[n<<1|1].lsum, Max(v[n<<1].sum, v[n<<1|1].sum));}void update(int l, int r, int d, int n) {      if (l<=v[n].l && v[n].r<=r) {            v[n].d = d;            v[n].lsum = v[n].rsum = v[n].sum = d==1?0:(r-l+1);            return ;      }      pushdown(n);      int mid = (v[n].l + v[n].r) >> 1;      if (r<=mid) {            update(l, r, d, n<<1);      } else if (l>mid) {            update(l, r, d, n<<1|1);      } else {            update(l, mid, d, n<<1);            update(mid+1, r, d, n<<1|1);      }      pushup(n);}int main(){      while (~scanf("%d%d", &n, &m)) {            build(1, n, 1);            vc.clear();            while (m--) {                  scanf("%s", s);                  if (s[0]=='N') {                        scanf("%d", &data);                        if (v[1].sum<data || data<=0) {                              printf("Reject New\n");                        } else {                              int idx = query(data, 1);                              update(idx, idx+data-1, 1, 1);                              printf("New at %d\n", idx);                              node p(idx, idx+data-1);                              it = upper_bound(vc.begin(), vc.end(), p, cmp);                              vc.insert(it, p);//二分找到比p大的位置,在it之前插入p                        }                  } else if (s[0]=='F') {                        scanf("%d", &data);                        node p(data, data);                        it = upper_bound(vc.begin(), vc.end(), p, cmp);                        //二分p比大的位置,如果p在该位置的前一个位置为合法                        int tmp = it-vc.begin()-1;                        if (tmp==-1 || data<vc[tmp].s || data>vc[tmp].e) {                              printf("Reject Free\n");                        } else {                              update(vc[tmp].s, vc[tmp].e, 0, 1);                              printf("Free from %d to %d\n", vc[tmp].s, vc[tmp].e);                              vc.erase(tmp+vc.begin());                        }                  } else if (s[0]=='G') {                        scanf("%d", &data);                        int tmp = vc.end()-vc.begin();                        if (data>tmp || data<=0) {                              printf("Reject Get\n");                        } else {                              printf("Get at %d\n", vc[data-1].s);                        }                  } else if (s[0]=='R') {                        update(1, n, 0, 1);                        printf("Reset Now\n");                        vc.clear();                  }            }printf("\n");      }      return 0;}


0 0