zoukankan      html  css  js  c++  java
  • 【AtCoder】ARC082 F

    【链接】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
    ",A);
        }
        return 0;
    }
    View Code
  • 相关阅读:
    STL与泛型编程-练习2-GeekBand
    HashSet
    JAVA集合
    分布式锁1 Java常用技术方案
    JAVA 锁
    JAVA多线程二
    JAVA多线程一
    Redis pipeline and list
    mongo 安装
    Intersection of Two Arrays
  • 原文地址:https://www.cnblogs.com/onioncyc/p/7492765.html
Copyright © 2011-2022 走看看