• LG P4373 [USACO18OPEN]Train Tracking P


    Description

    每天早晨特快列车会经过农场,开往大城市,每天下午它又会折回来,回到郊区。今天,Bessie 会花时间观察它,早晨和下午都会。

    Bessie 提前知道,列车有 $N$ 节车厢,方便起见,将其编号为 $0sim N-1$。车厢 $i$ 有一个 ID $c_i$。在早晨和下午,所有的数字都是可见的,所以对于每节车厢 Bessie 有两次机会观察它的 ID。也就是说,当列车早晨经过的时候,Bessie 能够观察 $c_0$,然后是 $c_1$,直到 $c_{N-1}$。当列车下午驶回的时候,她又一次能够观察 $c_0$,然后是 $c_1$,直到 $c_{N-1}$。

    Bessie 挑选了一个整数 $K$,她想要求出每个连续的 $K$ 节车厢中最小的 ID。她有一本能够帮助执行计算的笔记本,但是这个笔记本相当小,并且 Bessie 的手写(蹄写?)字相当大。比方说,可能没有足够的空间记下所有 $N+1-K$ 个最小值。由于某些神秘的原因,Bessie 满足于当她算出最小数的时候向天哞出这些数,所以这个问题至少还不成问题。

    列车马上就要来了!帮助 Bessie 在列车经过两次之后求出这 $N+1-K$ 个最小数,确保她有效地利用她有限的笔记本空间。她的笔记本被分为 $5500$ 个部分,方便起见编号为 $0sim 5499$,每个部分的空间恰好能够记录一个在 $[-2^{31} , 2^{31}-1]$ 之间的整数。最初的时候,每个部分都记录着整数 $0$。

    请帮助 Bessie 有效管理她有限的笔记本空间。

    Solution

    要求出多个区间最小值,如果没有空间限制,可以ST表/线段树解决

    此时要求空间限制$O(sqrt n)$,并且可以读入两遍数据

    第一遍读入数据:将下标为$0,sqrt n ,sqrt{2n},cdots ,n$的最小值算出,可以在读入数据时更新每个块的最小值,如果当前读入的位置是某个要求区间的右端点暴力扫所有块,时间复杂度$O(n)$,空间复杂度$O(sqrt n)$

    第二遍读入数据,将其他下标的最小值算出

    事实:$i+1$的区间中最小值取值位置一定不在$i$的区间中最小值取值位置之前

    那么对于左端点在同一个块内的所有最小值查询,最小值的取值位置在一个区间内,将这个区间分为两部分

    第一部分:与左端点在同一个块内的,这些位置可能会随着窗口移动而从左侧移出窗口,这部分的值用单调队列维护

    第二部分:与左端点不在同一个块,这些位置永远不会移出窗口,直接维护这一部分的最小值

    若读入数据时若已经到了某个询问的右端点,应该立即回答

    若已经读入到取值位置的区间的右端点,应该回答块内所有讯问

    对于最后一个块特殊处理,暴力去做

    时间复杂度$O(n)$,由于单调队列中至多$sqrt n$个元素,空间复杂度$O(sqrt n)$

    #include"grader.h"
    #include<algorithm>
    using namespace std;
    void helpBessie(int v){
        int cur=getCurrentCarIndex(),n=getTrainLength()-1,K=getWindowLength(),inf=0x7f7f7f7f,B=1000;
        if(!getCurrentPassIndex()){
            int i;
            if(!cur)for(int i=0;i*B<=n;i++)set(i,inf);
            if(v<get(cur/B))set(cur/B,v),set(cur/B+B,cur);
            for(i=get(5000);cur==n||cur==i*B+K-1;i++){
                if(i*B>n)break;
                int minn=inf,mnpos=0;
                for(int j=i;j<=(i*B+K-1)/B;j++){
                    int temp=get(j);
                    if(temp<minn)minn=temp,mnpos=get(j+B);
                }
                set(i+4000,mnpos);
            }
            if(cur<n)set(5000,i);
            else set(5000,0),set(5001,1);
        }
        else{
            int pos=get(5000),h=get(5001),t=get(5002),siz=1050;
            while(h<=t&&v<=get(t%siz))--t;
            ++t,set(t%siz,v),set(t%siz+siz,cur);
            for(;pos+K-1<=n;++pos){
                if(cur!=pos+K-1&&(pos/B==n/B||cur!=get(pos/B+4001)))break;
                while(h<=t&&get(h%siz+siz)<pos)++h;
                shoutMinimum(get(h%siz));
            }
            if(h<t&&cur/B>pos/B&&get((t-1)%siz+siz)/B>pos/B)--t;
            set(5000,pos),set(5001,h),set(5002,t);
        }
    }
    Train Tracking P
  • 相关阅读:
    Android为TV端助力:adb查找包名位置
    Android为TV端助力:RecyclerView更新数据时焦点丢失
    一个IOS自动化打包的脚本
    关于IOS免证书真机安装的过程和问题
    使用CoreAnimation 实现相机拍摄照片之后动画效果
    解决路由器无线中继连接不稳定的问题
    解决 an app id with identifier is not available. please enter a different string. xcode 7.3
    CoreText 关键性常用函数说明
    解决Xcode 7 http无法使用的问题
    解决IOS9 下在App中无法打开其他应用的问题
  • 原文地址:https://www.cnblogs.com/JDFZ-ZZ/p/14554309.html
Copyright © 2020-2023  润新知