题意:
现在有1到N(N <= 50000)个连续内存块,然后给出四种操作:
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表示起始的数字单元
现在有1到N(N <= 50000)个连续内存块,然后给出四种操作:
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的伤不起啊。记得上到网赛的cf85d就是找了个vector过的。恩,学。
线段树节点lsum,rsum,msum,cover,就是往常的意思。
做题过程:
貌似这题做了很久额。中间掺了网络赛和别的东西,再加上我昨天又睡得很晚,今天就废了。
有时候很奇怪,找一个东西,找很久都没有找到。比如说错误和一些东西。但是,我重新打一遍,就过了。
build a stone wall and do not fear.
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <set>
#include <vector>
#include <algorithm>
#define lson l,m , rt << 1
#define rson m + 1,r , rt << 1 | 1
#define maxn 50010
#define ls rt << 1
#define rs rt << 1 | 1
#define havem int m = (l + r) >> 1
using namespace std;
int a, b;
int lsum[maxn << 2],rsum[maxn << 2], msum[maxn << 2],cover[maxn << 2],x,n,m;
char op[10];
struct Node{
int st, end;
};
vector <Node> vec;
void build(int l, int r, int rt){
rsum[rt] = lsum[rt] = msum[rt] = r - l + 1;
cover[rt] = 0;
if(l == r) return ; havem;
build(lson); build(rson);
}
void push_dn(int rt, int m){
if(cover[rt] != -1){
cover[ls] = cover[rs] = cover[rt];
if(cover[rt] == 0){
lsum[ls] = rsum[ls] = msum[ls] = m - (m >> 1);
lsum[rs] = rsum[rs] = msum[rs] = (m >> 1);
}else{
lsum[ls] = rsum[ls] = msum[ls] = 0;
lsum[rs] = rsum[rs] = msum[rs] = 0;
}
cover[rt] = -1;
}
}
int query(int len, int l, int r, int rt){
if(l == r) {
return l;
}push_dn(rt, r - l + 1); havem;
if(msum[ls] >= len) return query(len,lson);
if(rsum[ls] + lsum[rs] >= len) return (m - rsum[ls] + 1);
// if(msum[rs] >= len) 这句话可以不要
return query(len,rson);
// return 0;
}
void push_up(int rt, int m){
lsum[rt] = lsum[ls];
rsum[rt] = rsum[rs];
msum[rt] = max (max(msum[ls],msum[rs]), rsum[ls] + lsum[rs]);
if(lsum[ls] == (m - (m >> 1))) lsum[rt] += lsum[rs];
if(rsum[rs] == (m >> 1)) rsum[rt] += rsum[ls];
if(cover[ls] == cover[rs]) cover[rt] = cover[ls];
}
void update(int L, int R, int cc, int l , int r, int rt){
if(L == l && r == R){
cover[rt] = cc;
lsum[rt] = rsum[rt] = msum[rt] = (cc == 0? r - l + 1:0);
return ;
}push_dn(rt, r - l + 1);
havem;
if(R <= m) update(L,R,cc,lson);
else if(L > m) update(L,R,cc,rson);
else update(L,m,cc,lson), update(m+ 1, R,cc,rson);
push_up(rt, r - l + 1);
}
bool cmp(const Node& b1, const Node& b2){
return b1.st < b2.st;
}
int main(){
char op[10];
while(scanf("%d%d",&n,&m) != EOF){
build(1,n,1);
vec.clear();
while(m --){
scanf("%s",op);
if(op[0] == 'R'){
printf("Reset Now\n");
update(1,n,0,1,n,1);
vec.clear();
}else if(op[0] == 'N'){
scanf("%d",&a);
if(msum[1] < a)
printf("Reject New\n");
else{
b = query(a,1,n,1);
printf("New at %d\n",b);
update(b, b + a- 1,1, 1, n, 1);
Node tmp;
tmp.st = b; tmp.end = b + a - 1;
if(vec.size() == 0)
vec.push_back(tmp);
else {
vector <Node > ::iterator it;
it = upper_bound(vec.begin(),vec.end(),tmp,cmp);
vec.insert(it,tmp);
}
}
}else if(op[0] == 'F'){
scanf("%d",&a);
Node tmp;
tmp.st = a; tmp.end = a;
vector<Node> ::iterator it;
it = upper_bound(vec.begin(),vec.end(),tmp,cmp);
if(it == vec.begin() || (--it)->end < a)
printf("Reject Free\n");
else {
printf("Free from %d to %d\n",it ->st, it->end);
update(it ->st, it -> end, 0, 1,n,1);
vec.erase(it);
}
}else{
scanf("%d",&a);
if(vec.size() < a)
printf("Reject Get\n");
else
printf("Get at %d\n",vec[a - 1].st);
}
}
printf("\n");
}
return 0;
}