空的标为1。两个操作。
将车停在离左右两边最近车最远的地方。如果有两个位置,输出编号小的位置。
编号为id的车离开停车场。
做题过程:
杂么什么都说跟那个hotel有点像。。。Orz。。。。
这个很有特色的就是push_up和查询了。
#include <iostream>
#include <cstring>
#include <cstdio>
#define lson l, m , rt << 1
#define rson m + 1, r, rt << 1 | 1
#define ls rt << 1
#define rs rt << 1 | 1
#define havem int m = (l + r ) >> 1
#define maxn 222222
using namespace std;
int op,id,pos[10 * maxn],n,m;
int lsum[maxn << 2], rsum[maxn << 2], msum[maxn << 2], beg[maxn << 2];
void build(int l, int r, int rt){
lsum[rt] = rsum[rt] = msum[rt] = r - l + 1;
beg[rt] = l;
if(l == r) return ;
havem;
build(lson); build(rson);
}
void push_up(int rt, int l, int r){
int m = r - l + 1;
lsum[rt] = lsum[ls] + (lsum[ls] == (m - (m >> 1)) ? lsum[rs]: 0);
rsum[rt] = rsum[rs] + (rsum[rs] == (m >> 1) ? rsum[ls] : 0);
msum[rt] = msum[ls] ; beg[rt] = beg[ls];//先初始化为左边的
if(rsum[ls] + lsum[rs] > msum[rt] + 1 || (rsum[ls] + lsum[rs] > msum[rt] && msum[rt] % 2 == 0)){
msum[rt] = rsum[ls] + lsum[rs];
beg[rt] = ( (l + r) >> 1 ) - rsum[ls] + 1;
}
if(msum[rs] > msum[rt] + 1 || (msum[rs] > msum[rt] && msum[rt] % 2 == 0)){
msum[rt] = msum[rs];
beg[rt] = beg[rs];
}
}
void update(int pos, int val, int l , int r, int rt){
if(l == r){
lsum[rt] = rsum[rt] = msum[rt] = (val == 0 ? 0 : 1);
return ;
}havem;
if(pos <= m) update(pos,val, lson);
else update(pos,val,rson);
push_up(rt, l , r);
}
int findpos(){
int final = 1, len = msum[1], s = beg[1];
if(s + len - 1 == n && s != 1){
final = n;
}else{
int mmax = lsum[1] - 1;
if((len - 1) / 2 > mmax){
mmax = (len - 1) / 2;
final = s + (len - 1) / 2;
}
if(rsum[1] - 1 > mmax){
mmax = rsum[1] - 1;
final = n;
}
}
return final;
}
int main(){
scanf("%d%d",&n,&m);
build(1,n,1);
for(int i = 0; i < m; i ++){
scanf("%d%d",&op,&id);
if(op == 1){
int ret = findpos();
printf("%d\n",ret);
update(ret, 0, 1, n, 1);
pos[id] = ret;
}else{
update(pos[id], 1, 1, n, 1);
}
}
return 0;
}