[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;
}
原文地址:https://www.cnblogs.com/wxjor/p/9494099.html