很优秀的一道题,做了各种线段树才感觉自己见的真的很少。
我们把每一层看做一个叶子节点,每段区间除了存储左右端点之外再存储一个 值, 表示在当前区间内剩下的某一层最长的宽度。
于是判断 的情况就只需要判断需要与 的大小即可,然后我们一边更新一边查找即可。
参考代码:
#include <bits/stdc++.h>
using namespace std;
const int Max=2e5+5;
struct Node{
int X,Y,Len;
}Tree[Max<<3];
int N,M,P;
void MakeTree(int P,int X,int Y){
Tree[P].X=X;Tree[P].Y=Y;Tree[P].Len=M;
if(X<Y){
MakeTree(P<<1,X,X+Y>>1);
MakeTree(P<<1|1,(X+Y>>1)+1,Y);
}
}
int Update_GetNum(int P,int Q){
if(Tree[P].X==Tree[P].Y){
Tree[P].Len-=Q;return Tree[P].X;
}
int Num=0;
if(Q<=Tree[P<<1].Len){
Num=Update_GetNum(P<<1,Q);
} else if (Q<=Tree[P<<1|1].Len){
Num=Update_GetNum(P<<1|1,Q);
}
Tree[P].Len=max(Tree[P<<1].Len,Tree[P<<1|1].Len);
return Num;
}
int main(){
int I,J,K;
while(~scanf("%d%d%d",&N,&M,&P)){
MakeTree(1,1,min(N,P));
for(I=1;I<=P;I++){
scanf("%d",&K);
if(Tree[1].Len<K){
puts("-1");
} else {
printf("%d\n",Update_GetNum(1,K));
}
}
}
return 0;
}