题目描述
刚拿到驾照的 KJ 总喜欢开着车到处兜风,玩完了再把车停到阿 Q 的停车场里,虽然她对自己停车的水平很有信心,但她还是不放心其他人的停车水平,尤其是 Kelukin。于是,她每次都把自己的爱车停在距离其它车最远的一个车位。KJ 觉得自己这样的策略非常科学,于是她开始想:在一个停车场中有一排车位,从左到右编号为 1 到 n,初始时全部是
空的。有若干汽车,进出停车场共 m 次。对于每辆进入停车场的汽车,会选择与其它车距离最小值最大的一个车位,若有多个符合条件,选择最左边一个。KJ 想着想着就睡着了,在她一旁的 Kelukin 想帮她完成这个心愿,但是他又非常的懒,不愿意自己动手,于是就把这个问题就留给了你:在 KJ 理想的阿 Q 的停车场中,给你车辆进出的操作序列,依次输
出每辆车的车位编号。
输入
第一行,两个整数 n 和 m,表示停车场大小和操作数;
接下来 m 行,每行两个整数 F 和 x
F 是 1 表示编号为 x 的车进停车场;
F 是 2 表示编号为 x 的车出停车场;
保证操作合法,即:
出停车场的车一定目前仍在停车场里;
停车场内的车不会超过 n;
输出
对于所有操作 1,输出一个整数,表示该车车位的编号
样例输入
7 11
1 15
1 123123
1 3
1 5
2 123123
2 15
1 21
2 3
1 6
1 7
1 8
样例输出
1
7
4
2
7
4
1
3
- 翻译一下题目,就是叫你把一个[1,n]的区间每次找到“最长”的那一段,输出那段的中间点(停车的位置),特殊判断[1,p]:停车在1 和 [q,n]:停车在n.
- 方法一:用线段树做,每次停车,将停车位置上的权值视为0,每次开走,将停车位置上的权值视为1. 用上传更新(我这样叫它:push_pu())的方法更新每段区间内的最长线段mx和最长线段的起始位置mxpos。为了更新最长线段,需要记录区间左端开始的最长线段lmx和右段开始的最长线段rmx。就像hotel那道题一样。特殊的是,最长线段mx不必再包含区间两端的lmx和rmx,因为并没什么用。最后Quary的时候要特殊判断。
- 方法二:用优先队列做,把停车后截成的小线段进队列,判断当前的最大线段是否合理用树状数组。在用链表记录一下车左右的车的位置,就差不多了。
#include<cstdio>
#define MAXN 200000
#define MAXNUM 2000000
struct node{
int l,r;
int lmx,rmx,mx,mxpos;
}tree[MAXN*4+100];
int n,m,car[MAXNUM+10];
void build(int i,int l,int r)
{
tree[i].l=l,tree[i].r=r;
tree[i].lmx=tree[i].rmx=tree[i].mx=r-l+1;
tree[i].mxpos=l;
if(l==r) return ;
int mid=(l+r)/2;
build(i*2,l,mid);
build(i*2+1,mid+1,r);
}
int Weight(int len)
{
if(!len) return 0;
return (len-1)/2+1;
}
void Adjust(int i,int len,int st)
{
if(!len) return ;
int g=Weight(tree[i].mx),h=Weight(len);
if(g<h) tree[i].mx=len,tree[i].mxpos=st;
else if(g==h && st<tree[i].mxpos) tree[i].mxpos=st;
}
void push_up(int i)
{
tree[i].lmx=tree[i*2].lmx,tree[i].rmx=tree[i*2+1].rmx;
if(tree[i].lmx==tree[i*2].r-tree[i*2].l+1)
tree[i].lmx+=tree[i*2+1].lmx;
if(tree[i].rmx==tree[i*2+1].r-tree[i*2+1].l+1)
tree[i].rmx+=tree[i*2].rmx;
//标记好mx=0,impossible;mx不用一并包含lmx和rmx
tree[i].mxpos=0,tree[i].mx=0;
Adjust(i,tree[i*2].rmx+tree[i*2+1].lmx,tree[i*2].r-tree[i*2].rmx+1);
Adjust(i,tree[i*2].mx,tree[i*2].mxpos);
Adjust(i,tree[i*2+1].mx,tree[i*2+1].mxpos);
}
void insert(int i,int inpos,int d)
{
if(tree[i].l==inpos && tree[i].r==inpos){
tree[i].lmx=tree[i].rmx=tree[i].mx=d;
if(d)
tree[i].mxpos=tree[i].l;
else
tree[i].mxpos=0;
return ;
}
int mid=(tree[i].l+tree[i].r)/2;
if(inpos<=mid) insert(i*2,inpos,d);
else insert(i*2+1,inpos,d);
push_up(i);
}
int Quary()
{
int len=(tree[1].mx-1)/2+1,ret=(tree[1].mxpos*2+tree[1].mx-1)/2;
if(tree[1].lmx>=len) ret=1;
else if(tree[1].rmx>len) ret=n;
return ret;
}
int main()
{
int p,num,inpos;
scanf("%d%d",&n,&m);
build(1,1,n);
for(int i=1;i<=m;i++){
scanf("%d%d",&p,&num);
if(p==1){
inpos=Quary();
printf("%d\n",inpos);
car[num]=inpos;
insert(1,inpos,0);
}
else{
inpos=car[num];
insert(1,inpos,1);
car[num]=0;
}
}
}
错误代码:还不知道怎么错了!!!!!!!!
#include<cstdio>
#define MAXN 200000
#define MAXNUM 2000000
struct node{
int l,r;
int lmax,rmax,maxx,mxpos;
}tree[MAXN*4+100];
int n,m,car[MAXNUM+10];
void build(int i,int l,int r)
{
tree[i].l=l,tree[i].r=r;
tree[i].lmax=tree[i].rmax=tree[i].maxx=r-l+1;
tree[i].mxpos=l;
if(l==r) return ;
int mid=(l+r)/2;
build(i*2,l,mid);
build(i*2+1,mid+1,r);
}
void revise(int i,int len,int pos)
{
tree[i].lmax=tree[i].rmax=tree[i].maxx=len;
tree[i].mxpos=pos;
}
int Interval(node a)
{
return a.r-a.l+1;
}
int Weight(int l,int len)
{
if(!len) return -1;
if(l==1) return len;
if(l+len-1==n) return len;
return (len-1)/2+1;
}
void Adjust(int i,int tmp,int tmpl)
{
int a=Weight(tree[i].mxpos,tree[i].maxx),b=Weight(tmpl,tmp);
if(a<b)
tree[i].maxx=tmp,tree[i].mxpos=tmpl;
else if(a==b && tree[i].mxpos>tmpl)
tree[i].mxpos=tmpl;
}
void insert(int i,int inpos,int d)
{
if(tree[i].l==inpos && tree[i].r==inpos){
if(d) revise(i,1,tree[i].l);
else revise(i,0,0);
return ;
}
int mid=(tree[i].l+tree[i].r)/2;
if(inpos<=mid) insert(i*2,inpos,d);
else insert(i*2+1,inpos,d);
tree[i].lmax=tree[i*2].lmax,tree[i].rmax=tree[i*2+1].rmax;
if(tree[i].lmax==Interval(tree[i*2]))
tree[i].lmax+=tree[i*2+1].lmax;
if(tree[i].rmax==Interval(tree[i*2+1]))
tree[i].rmax+=tree[i*2].rmax;
tree[i].maxx=tree[i].lmax;
tree[i].mxpos=tree[i].l;
Adjust(i,tree[i].rmax,tree[i].r-tree[i].rmax+1);
Adjust(i,tree[i*2].rmax+tree[i*2+1].lmax,tree[i*2].r-tree[i*2].rmax+1);
Adjust(i,tree[i*2].maxx,tree[i*2].mxpos);
Adjust(i,tree[i*2+1].maxx,tree[i*2+1].mxpos);
}
int Quary()
{
int len=(tree[1].maxx-1)/2+1,ret=(tree[1].mxpos*2+tree[1].maxx-1)/2;
if(tree[1].lmax>=len) len=tree[1].lmax,ret=1;
if(tree[1].rmax>len) ret=n;
return ret;
}
int main()
{
int p,num;
scanf("%d%d",&n,&m);
build(1,1,n);
for(int i=1;i<=m;i++){
scanf("%d%d",&p,&num);
if(p==1){
int pos=Quary();
printf("%d\n",pos);
car[num]=pos;
insert(1,pos,0);
}
else{
int pos=car[num];
insert(1,pos,1);
car[num]=0;
}
}
}