HDU P2795 Billboard 【线段树】

很优秀的一道题,做了各种线段树才感觉自己见的真的很少。

我们把每一层看做一个叶子节点,每段区间除了存储左右端点之外再存储一个 L e n 值, L e n 表示在当前区间内剩下的某一层最长的宽度。

于是判断 1 的情况就只需要判断需要与 T r e e [ 1 ] . L e n 的大小即可,然后我们一边更新一边查找即可。

参考代码:

#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;
}

猜你喜欢

转载自blog.csdn.net/yanzhenhuai/article/details/81252881
今日推荐