hdu2871 Memory Control 线段树,二分

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

#include 
#include 
#include 
#include 
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 vc;
vector::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].sumvc[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;
}


你可能感兴趣的:(线段树/树状数组)