题目链接:hdu2871
/*hdu 2871 区间合并,成段更新,vector
poj 3667 升级版
题意:现在有1到N(N <= 50000)个连续内存单元,连续的n块内存单元能
组成一个内存块,然后给出四种操作:
1. Reset 释放所有内存块,并且输出“Reset Now”。
2. New x 申请一块有连续x个内存单元的空间,如果有多个,选择最左端的,
然后输出“New at A", A表示最左端的那个内存单元;否则输出“Reject New”。
3. Free x 释放包含第x个内存单元的那个内存块,并且输出“Free from A to B”,
A到B表示内存块的左右端点;否则输出“Reject Free”。
4. Get x 找到第x个内存块,如果找到,输出“Get at A”,
A表示第x块内存块的最左端的内存单元编号,否则输出“Reject Get”。
注意:内存块的编号从左到右依次增大
思路:
用一个vector来保存申请的内存块的左右端点,在vector中的位置就
表示内存块的编号,当申请一个内存块时,二分查找这个内存块在vector中的
位置,然后插入
*/
#include <iostream>
#include <algorithm>
#include <vector>
#include <cstdio>
using namespace std;
#define lson rt<<1
#define rson rt<<1|1
const int N = 500010;
struct node
{
int l,r,c;
int lsum,rsum,sum;
}s[N<<2];
struct block
{
int l,r;
bool operator < (const block &cmp) const{
return l < cmp.l;
}
};
void pushdown(int rt, int m)
{
if(s[rt].c != -1){
s[lson].lsum = s[lson].rsum = s[lson].sum = s[rt].c?0:m-(m>>1);
s[rson].lsum = s[rson].rsum = s[rson].sum = s[rt].c?0:m>>1;
s[lson].c = s[rson].c = s[rt].c;
s[rt].c = -1;
}
}
void pushup(int rt, int m)
{
s[rt].lsum = s[lson].lsum;
s[rt].rsum = s[rson].rsum;
s[rt].sum = max(s[lson].sum, s[rson].sum);
if(s[lson].lsum == m-(m>>1))
s[rt].lsum += s[rson].lsum;
if(s[rson].rsum == m>>1)
s[rt].rsum += s[lson].rsum;
s[rt].sum = max(s[rt].sum, s[lson].rsum + s[rson].lsum);
}
void build(int l, int r, int rt)
{
s[rt].l = l; s[rt].r = r;
s[rt].lsum = s[rt].rsum = s[rt].sum = r-l+1;
s[rt].c = -1;
if(l == r) return;
int mid = (l+r) >> 1;
build(l, mid, lson);
build(mid+1, r, rson);
}
void updata(int c, int l, int r, int rt)
{
if(l <= s[rt].l && s[rt].r <= r){
s[rt].c = c;
s[rt].lsum = s[rt].rsum = s[rt].sum = c?0:s[rt].r-s[rt].l+1;
return;
}
pushdown(rt, s[rt].r-s[rt].l+1);
int mid = (s[rt].l+s[rt].r)>>1;
if(l <= mid)
updata(c, l, r, lson);
if(mid < r)
updata(c, l, r, rson);
pushup(rt, s[rt].r-s[rt].l+1);
}
int query(int num, int rt)
{
if(s[rt].l == s[rt].r) return s[rt].l;
int mid = (s[rt].l + s[rt].r) >> 1;
pushdown(rt, s[rt].r-s[rt].l+1);
if(s[lson].sum >= num)
return query(num, lson);
if(s[lson].rsum + s[rson].lsum >= num)
return mid-s[lson].rsum + 1;
//if(s[rson].sum >= num)
return query(num, rson);
}
vector <block> v;
int main()
{
int n,m,x;
char a[10];
while(~scanf("%d%d",&n,&m))
{
build(1, n, 1);
v.clear();
while(m--){
scanf("%s",a);
if(a[0] == 'N'){//申请内存块
scanf("%d",&x);
if(s[1].sum < x) puts("Reject New");
else{
int pos = query(x, 1);//找到最左端的那个内存单元的编号
printf("New at %d\n",pos);
updata(1, pos, pos+x-1, 1);//更新
block tmp;
tmp.l = pos; tmp.r = pos+x-1;
vector<block>::iterator iter;//索引
iter = upper_bound(v.begin(), v.end(), tmp);//二分查找
v.insert(iter, tmp);
}
}
if(a[0] == 'F'){//释放内存块
scanf("%d",&x);
block tmp;
tmp.l = tmp.r = x;//假设第x个内存单元是一个内存块
vector<block>::iterator iter;
iter = upper_bound(v.begin(), v.end(), tmp);
int pos = iter - v.begin() - 1;//upper_bound()返回的是大于tmp的第一个值
if(pos == -1 || v[pos].r < x)
puts("Reject Free");
else{
printf("Free from %d to %d\n", v[pos].l, v[pos].r);
updata(0, v[pos].l, v[pos].r, 1);
v.erase(v.begin()+pos);//删除
}
}
if(a[0] == 'G'){
scanf("%d",&x);
if(x > v.size())
puts("Reject Get");
else
printf("Get at %d\n",v[x-1].l);//vector是从0开始的
}
if(a[0] == 'R'){
updata(0, 1, n, 1);
v.clear();
puts("Reset Now");
}
}
printf("\n");
}
return 0;
}