//HDU 2871 Memory Control 线段树 : 区间合并 单点更新 容器的使用
/*
题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=2871
题目大意:现在有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”。
思路:其实就是模拟内存的操作,用线段树优化。
*/
#include<iostream>
#include<stdio.h>
#include<vector>
#include<algorithm>
#include<string.h>
#include<stdlib.h>
using namespace std;
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define N 50005
int msum[N<<2],lsum[N<<2],rsum[N<<2];
int cov[N<<2];
int n,m;
struct node{
int from;
int to;
};
vector<node>V;
int cmp(const node &a,const node &b){
return a.from < b.from;
}
void pushup(int rt,int m){
lsum[rt] = lsum[rt<<1];
rsum[rt] = rsum[rt<<1|1];
if(lsum[rt] == (m-(m>>1))) lsum[rt] += lsum[rt<<1|1];
if(rsum[rt] == (m>>1)) rsum[rt] += rsum[rt<<1];
msum[rt] = max(rsum[rt<<1]+lsum[rt<<1|1],max(msum[rt<<1],msum[rt<<1|1]));
}
void pushdown(int rt,int m){
if(cov[rt]!=-1){
cov[rt<<1] = cov[rt<<1|1] = cov[rt];
msum[rt<<1] = lsum[rt<<1] = rsum[rt<<1] = (m-(m>>1))*cov[rt];
msum[rt<<1|1] = lsum[rt<<1|1] = rsum[rt<<1|1] = (m>>1)*cov[rt];
cov[rt] = -1;
}
}
void build(int rt,int l,int r){
if(l == r){
msum[rt] = lsum[rt] = rsum[rt] = 1;
return ;
}
int mid = (r + l) >> 1;
build(lson);
build(rson);
pushup(rt,r-l+1);
}
void update(int rt,int l,int r,int L,int R,int c){
if(L <= l && R >= r){
cov[rt] = c;
msum[rt] = lsum[rt] = rsum[rt] = (r-l+1)*c;
return ;
}
pushdown(rt,r-l+1);
int mid = (r + l) >> 1;
if(L <= mid) update(lson,L,R,c);
if(R > mid ) update(rson,L,R,c);
pushup(rt,r-l+1);
}
int query(int rt,int l,int r,int x){
if(msum[rt] < x)
return 0;
if(l == r)
return l;
pushdown(rt,r-l+1);
int mid = (r + l) >> 1;
if(msum[rt<<1] >= x) return query(lson,x);
else if(rsum[rt<<1] + lsum[rt<<1|1] >= x) return mid-rsum[rt<<1]+1;
else return query(rson,x);
}
int main(){
int i,j,res,tmp;
char s[10];
while(scanf("%d %d",&n,&m)!=EOF){
build(1,1,n);
V.clear();
memset(cov,-1,sizeof(cov));
// printf("--------------------------------------\n");
// for(i = 1; i <= 12; ++i)
// printf("i:%d msum :%d lsum: %d rsum:%d\n",i,msum[i],lsum[i],rsum[i]);
//
// printf("--------------------------------------\n");
while(m--){
scanf("%s",s);
if(s[0] == 'N'){
scanf("%d",&res);
if(msum[1] < res)
puts("Reject New");
else{
tmp = query(1,1,n,res);
printf("New at %d\n",tmp);
update(1,1,n,tmp,tmp+res-1,0);
node p;
p.from = tmp;
p.to = tmp+res-1;
vector<node>::iterator it;
it = upper_bound(V.begin(),V.end(),p,cmp);
V.insert(it,p);
}
}
else if(s[0] == 'F'){
scanf("%d",&res);
node p;
p.from = res;
p.to = res;
vector<node>::iterator it;
it = upper_bound(V.begin(),V.end(),p,cmp);
int tmp = it - V.begin() - 1;
if(tmp == -1 || V[tmp].to<res)
puts("Reject Free");
else{
printf("Free from %d to %d\n", V[tmp].from, V[tmp].to);
update(1,1,n,V[tmp].from,V[tmp].to,1);
V.erase(V.begin()+tmp);
}
}
else if(s[0] == 'G'){
scanf("%d",&res);
if(res > V.size())
puts("Reject Get");
else
printf("Get at %d\n",V[res-1].from);
}
else if(s[0] == 'R'){
update(1,1,n,1,n,1);
V.clear();
puts("Reset Now");
}
// printf("--------------------------------------\n");
// for(i = 1; i <= 12; ++i)
// printf("i:%d msum :%d lsum: %d rsum:%d\n",i,msum[i],lsum[i],rsum[i]);
// printf("--------------------------------------\n");
}
printf("\n");
}
return 0;
}
HDU 2871 Memory Control 线段树 区间合并 单点更新 容器的使用
最新推荐文章于 2024-09-22 12:24:05 发布