zoukankan      html  css  js  c++  java
  • [Arc082F]Sandglass

    [Arc082F] Sandglass

    Description

    有一个沙漏由两个上下相通玻璃球A和B构成,这两个玻璃球都含有一定量的沙子,我们暂且假定AB中位于上方的玻璃球的为U,下方的玻璃球为L,则除非U中没有沙子,否则每秒钟都会有1克沙子从U掉入L。在第0个时刻,A中有a克沙子,B中有X?a克沙子(总共有X克沙子),且U为A,L为B(即A上B下)。在r1,r2,...,rK这些时刻,我们将倒转整个沙漏,使得原来的U变成L,原来的L变成U。对于翻转操作,t时刻是指从第0个时刻起经过t秒后的时刻,我们可以将翻转沙漏的操作看做瞬间完成的。现在有Q次询问,每一次询问会给定一对非负整数(ti,ai),求a=ai,第ti时刻,A中所含沙子的克数。

    Input

    第一行一个正整数X
    第二行一个正整数K
    第三行K个整数,表示r1,r2,...,rK
    接下来一行一个正整数Q
    接下来Q行,每行两个非负整数,分别表示每次次询问的(ti,ai)

    Output

    一共Q行对于每次询问,输出一行一个非负整数表示答案。

    Sample Input

    Sample 1

    180
    3
    60 120 180
    3
    30 90
    61 1
    180 180

    Sample 2

    100
    1
    100000
    4
    0 100
    90 100
    100 100
    101 100

    Sample 3

    100
    5
    48 141 231 314 425
    7
    0 19
    50 98
    143 30
    231 55
    342 0
    365 100
    600 10

    Sample Output

    Sample 1

    60
    1
    120

    Sample 2

    100
    10
    0
    0

    Sample 3

    19
    52
    91
    10
    58
    42
    100

    HINT

    (1leq x leq 10^9,1leq kleq 10^5)
    所有输入数据均为非负整数

    试题分析

    数形结合:考虑每一个翻转时刻的以a为x轴,剩余沙子数量为y轴的图像。
    那么可以发现当沙子在流失的时候图像逐渐下移,碰到0的部分就变成了0。
    当沙子在流入的时候图像上移,碰到X的部分就变成了X。
    然而图像在0时刻一开始是一段斜率为1的直线,原先被“压缩”成为一条直线的部分不会随着变化展开,所以整个过程图像都在压缩。
    于是发现这是一个三段函数,直接记录上面的和下面的转折点然后计算即可。
    代码写的丑了点

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<vector>
    #include<algorithm>
     
    using namespace std;
    #define LL long long
     
    inline LL read(){
        LL x=0,f=1; char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const LL INF = 2147483600;
    const LL MAXN = 100010;
     
    LL flip[MAXN+1][2],up[MAXN+1][2];
    LL X,N,t[MAXN+1],Q;
     
    int main(){
        X=read(),N=read(); bool lossing=1;
        LL l=0,r=X; up[0][0]=l,up[0][1]=r;
        flip[0][0]=0; flip[0][1]=X;
        for(LL i=1;i<=N;i++) {
            t[i]=read();
            if(lossing) {
                flip[i][0]=flip[i-1][0]; flip[i][1]=flip[i-1][1];
                flip[i][0]=max(flip[i][0],flip[i][0]-(l-(t[i]-t[i-1])));
                l=max(0LL,l-(t[i]-t[i-1])),r=max(0LL,r-(t[i]-t[i-1]));
            }
            else {
                flip[i][0]=flip[i-1][0]; flip[i][1]=flip[i-1][1];
                flip[i][1]=min(flip[i][1],flip[i][1]-(r+(t[i]-t[i-1])-X));
                l=min(X,l+(t[i]-t[i-1])),r=min(X,r+(t[i]-t[i-1]));  
            } if(flip[i][1]<flip[i][0]) flip[i][0]=flip[i][1];
            up[i][0]=l; up[i][1]=r;
            lossing^=1;
        } Q=read();
        while(Q--){
            LL tim=read(),A=read(),x=upper_bound(t,t+N+1,tim)-t-1;
            LL Add=tim-t[x];
            if(!(x&1)) Add=-Add;
            if(flip[x][0]==flip[x][1]){ printf("%lld
    ",min(X,max(Add+up[x][0],0LL))); continue;}
            else {
                if(A<=flip[x][0]) printf("%lld
    ",min(X,max(Add+up[x][0],0LL)));
                else if(A>flip[x][0]&&A<flip[x][1]) printf("%lld
    ",min(X,max(Add+up[x][0]+A-flip[x][0],0LL)));
                else  printf("%lld
    ",min(X,max(Add+up[x][1],0LL)));
            }
        }
        return 0;
    }
    
  • 相关阅读:
    【Linux开发】linux设备驱动归纳总结(三):5.阻塞型IO实现
    【Linux开发】linux设备驱动归纳总结(三):5.阻塞型IO实现
    【Linux】linux设备驱动归纳总结
    【Linux】linux设备驱动归纳总结
    【Linux开发】linux设备驱动归纳总结(三):4.ioctl的实现
    【Linux开发】linux设备驱动归纳总结(三):4.ioctl的实现
    【Linux开发】linux设备驱动归纳总结(三):3.设备驱动面向对象思想和lseek的实现
    【Linux开发】linux设备驱动归纳总结(三):3.设备驱动面向对象思想和lseek的实现
    【Linux开发】linux设备驱动归纳总结(三):2.字符型设备的操作open、close、read、write
    【Linux开发】linux设备驱动归纳总结(三):2.字符型设备的操作open、close、read、write
  • 原文地址:https://www.cnblogs.com/wxjor/p/9494099.html
Copyright © 2011-2022 走看看