【AtCoder】ARC082 F - Sandglass

【链接】F - Sandglass

【题意】给定沙漏A和B,分别装着a和X-a的沙子,开始时A在上B在下,每秒漏1,漏完不再漏。给定n,有n个时刻ai沙漏倒转。给定m个询问,每次询问给定初值a和时刻t,求A中沙子量。

【算法】数学(函数)

【题解】

先不考虑时刻,令ft(a)表示沙子初值a时,当前A中的沙子数。(x轴是初值a,y轴是沙子数num)

时刻为0时,显然是一条从0出发斜率为1的直线。

若A在上,则每过1s,整段函数都下移一个单位,碰到y=0则变成平的。

若A在下,则每过1s,整段函数都上移一个单位,碰到y=X则变成平的。

而不平的部分,斜率恒为1

这样,这个函数始终是一个三段函数,可以按时间顺序维护两个转折点的位置就可以快速出解。

复杂度O(m)。

然而这个函数还有一些特殊的性质,所以可以更方便地写程序。

我们维护斜率为1的原y=x+b,其中b就是变化量,这样f(A)就是A+b,判断一下A+b和两个转折点y值的关系即可。

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=100010;
int n,m,a[maxn];
int calc(int l,int r,int x)
{return max(l,min(r,x));}
int main(){
    int X;
    scanf("%d%d",&X,&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    int L,R=X;//初值……
    int t=0,k=0,s=-1,x=0;
    int time,A;
    scanf("%d",&m);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&time,&A);
        while(k<n&&a[k+1]<=time){
            int dif=s*(a[k+1]-t);
            L=calc(0,X,L+dif);
            R=calc(0,X,R+dif);
            s*=-1;
            x+=dif;
            t=a[k+1];
            k++;
        }
        int T=time-t;
        A=calc(L,R,A+x);
        A=calc(0,X,A+s*T);
        printf("%d\n",A);
    }
    return 0;
}
View Code

 

转载于:https://www.cnblogs.com/onioncyc/p/7492765.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值