hdu 2871 Memory Control 伸展树区间合并

题意:就是对一个区间的四种操作,NEW x,占据最左边的连续的x个单元,Free x 把x单元所占的连续区间清空 , Get x 把第x次占据的区间输出来, R 清空整个区间。

解法:很明显的区间合并,跟hotel那题差不多,貌似多了Free,Get操作, 

我们可以用一个vector保存已经申请的区间,然后要Free x就在vector里面二分找到x所在的区间即可, Get也是二分一下即可, 其它操作可以用线段树或者伸展树操作。

这题主要是练了一下伸展树,这题也算基础, 但还是调了好久,真心难调,锻炼调试能力。

伸展树:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 50006;
#define L ch[x][0]
#define R ch[x][1]
#define KT ch[ ch[root][1]][0]
#define mp make_pair
typedef pair<int, int> pii;
int n;
struct splayTree {
    int sz[maxn], pre[maxn], ch[maxn][2];
    int top, root;
    int ls[maxn], rs[maxn], ms[maxn], col[maxn], val[maxn];
    void rotate(int &x, int f) {
        int y = pre[x], z = pre[y];
        down(y); down(x);
        ch[y][!f] = ch[x][f];
        pre[ch[x][f]] = y;
        pre[x] = pre[y];
        if(z) ch[z][ch[z][1] == y] = x;
        ch[x][f] = y;
        pre[y] = x;
        up(y);
    }
    void splay(int &x, int g) {
    	down(x);
          while(pre[x] != g) {
              int y = pre[x], z = pre[y];
              if(z == g) rotate(x, ch[y][0] == x);
              else {
                  int f = (ch[z][0] == y);
                  ch[y][!f] == x ? rotate(y, f) : rotate(x, !f);
                  rotate(x, f);
              }
          }
          up(x);
          if(!g) root = x;
      }
    void rto(int k, int g) {
        int x = root;
        while(sz[L] != k) {
        	down(x);
            if(sz[L] > k) x = L;
            else {
                k -= sz[L]+1;
                x = R;
            }
        }
        splay(x, g);
    }
    void newNode(int &x, int v, int fa) {
         x = ++top;
         sz[x] = 1;
         pre[x] = fa;
         L = R = 0;
         col[x] = -1;
         ls[x] = rs[x] = ms[x] = val[x] = v;
    }
    void down(int x) {
    	if(~col[x]) {
    		col[L] = col[R] = val[L] = val[R] = col[x];
    		ls[L] = rs[L] = ms[L] = col[x] * sz[L];
    		ls[R] = rs[R] = ms[R] = col[x] * sz[R];
    		col[x] = -1;
    	}
    }

    void up(int x) {
        sz[x] = sz[L] + sz[R] + 1;
        ls[x] = ls[L];
        rs[x] = rs[R];
        ms[x] = max(ms[L], ms[R]);
        if(val[x]) {
        	ms[x] = max(ms[x], rs[L]+1+ls[R]);
        	if(ls[x] == sz[L]) ls[x] += ls[R]+1;
        	if(rs[x] == sz[R]) rs[x] += rs[L]+1;
        }
    }
    void build(int &x, int l, int r, int fa) {
        if(l > r) return;
        int m = (l + r) >> 1;
        newNode(x, 1, fa);
        build(L, l, m-1, x);
        build(R, m+1, r, x);
        up(x);
    }

    void init(int n) {
        top = 0;
        newNode(root, 0, 0);
        newNode(ch[root][1], 0, root);
        build(KT, 0, n-1, ch[root][1]);
        up(ch[root][1]); up(root);
    }
    void update(int l, int r, int c) {
        rto(l-1, 0);
        rto(r+1, root);
        col[KT] = val[KT] = c;
        ls[KT] = rs[KT] = ms[KT] = c*sz[KT];
        up(ch[root][1]);
        up(root);
    }
    int find(int x, int k, int pos) {	//找连续的空位的首位置
    	down(x);
    	if(ms[L] >= k) return find(L, k, pos);
    	pos += sz[L];
    	if(val[x] && rs[L]+ls[R]+1 >= k) return pos - rs[L];
    	return find(R, k, pos+1);
    }
}spt;
vector<pii> vec;
int main() {
	char op[22];
	int j, m, x;
	while (~scanf("%d%d", &n, &m)) {
		spt.init(n);
		vec.clear();
		while (m--) {
			scanf("%s", op);
			if (op[0] == 'R') {
				vec.clear();
				puts("Reset Now");
				spt.update(1, n, 1);
				continue;
			}
			scanf("%d", &x);
			if (op[0] == 'N') {
				if (spt.ms[spt.root] < x) {
					puts("Reject New");
					continue;
				}
				int l = spt.find(spt.root, x, 0);
				printf("New at %d\n", l);
				int r = l + x - 1;
				spt.update(l, r, 0);
				pii tp = mp(l, r);
				j = lower_bound(vec.begin(), vec.end(), tp) - vec.begin();
				vec.insert(vec.begin() + j, tp);
			} else if (op[0] == 'G') {
				if ((int) vec.size() < x)
					puts("Reject Get");
				else
					printf("Get at %d\n", vec[x - 1].first);
			} else if (op[0] == 'F') {

				j = upper_bound(vec.begin(), vec.end(), mp(x, n + 3))
						- vec.begin() - 1;
				if (j == -1 || vec[j].first > x || vec[j].second < x)
					puts("Reject Free");
				else {

					printf("Free from %d to %d\n", vec[j].first, vec[j].second);
					spt.update(vec[j].first, vec[j].second, 1);
					vec.erase(vec.begin() + j);
				}
			}
		}
		puts("");
	}
	return 0;
}


线段树:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int maxn = 50006;
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
#define ls rt<<1
#define rs rt<<1|1
#define Mid int m = (l+r) >> 1
#define mp make_pair
typedef pair<int, int> pii;
int n;
struct segTree {
    int lsum[maxn<<2], rsum[maxn<<2], msum[maxn<<2];
    int col[maxn<<2];
    inline void up(int l, int r, int rt) {
        msum[rt] = max(msum[ls], msum[rs]);
        msum[rt] = max(msum[rt],  rsum[ls] + lsum[rs]);
        Mid;
        lsum[rt] = lsum[ls];
        if (lsum[ls] == m - l + 1) lsum[rt] += lsum[rs];
        rsum[rt] = rsum[rs];
        if (lsum[rs] == r - m) rsum[rt] += rsum[ls];
    }
    inline void down(int l, int r, int rt) {
        if (~col[rt]) {
            col[ls] = col[rs] = col[rt];
            Mid;
            lsum[ls] = rsum[ls] = msum[ls] = col[rt] * (m - l + 1);

            lsum[rs] = rsum[rs] = msum[rs] = col[rt]* (r - m );
            col[rt] = -1;
        }
    }
    void build(int l = 1, int r = n, int rt = 1) {
        lsum[rt] = rsum[rt] = msum[rt] = r - l + 1;
        col[rt] = -1;
        if (l == r)
            return;
        Mid;
        build(lson);
        build(rson);
  //      up(l, r, rt);
    }
    void update(int L, int R, int v, int l = 1, int r = n, int rt = 1) {
        if (L <= l && r <= R) {
            col[rt] = v;
            rsum[rt] = lsum[rt] = msum[rt] = v * (r - l + 1);
            return;
        }
        Mid;
        down(l, r, rt);
        if (L <= m)
            update(L, R, v, lson);
        if (R > m)
            update(L, R, v, rson);
        up(l, r, rt);
    }
    int find(int x, int l = 1, int r = n, int rt = 1) {
        if (l == r)
            return l;
        Mid;
        down(l, r, rt);
        if (msum[ls] >= x)
            return find(x, lson);
        else if (rsum[ls] + lsum[rs] >= x)
            return m - rsum[ls] + 1;
        else
       return find(x, rson);
    }
} tree;
vector<pii > vec;
int main() {
    char op[22];
    int j, m, x;
    while (~scanf("%d%d", &n, &m)) {
        tree.build();
        vec.clear();
        while (m--) {
            scanf("%s", op);
            if (op[0] == 'R') {
                vec.clear();
                puts("Reset Now");
                tree.update(1, n, 1);
                continue;
            }
            scanf("%d", &x);
            if (op[0] == 'N') {
                if (tree.msum[1] < x) {
                    puts("Reject New");
                    continue;
                }
                int l = tree.find(x);
                printf("New at %d\n", l);
                int r = l + x - 1;
                tree.update(l, r, 0);
                pii tp = mp(l, r);
                j = lower_bound(vec.begin(), vec.end(), tp) - vec.begin();
                vec.insert(vec.begin()+j, tp);
            } else if (op[0] == 'G') {
                if ((int) vec.size() < x)
                    puts("Reject Get");
                else
                    printf("Get at %d\n", vec[x - 1].first);
            } else if (op[0] == 'F') {

                j = upper_bound(vec.begin(), vec.end(), mp(x, n + 3))
                        - vec.begin() - 1;
                if (j == -1 || vec[j].first > x || vec[j].second < x)
                //if(j == -1)
                    puts("Reject Free");
                else {

                    printf("Free from %d to %d\n", vec[j].first, vec[j].second);
                    tree.update(vec[j].first, vec[j].second, 1);
                    vec.erase(vec.begin() + j);
                }
            }
        }
        puts("");
    }
    return 0;
}



你可能感兴趣的:(伸展树)