• [arc082f]sandglass


    Description

    有一个沙漏由两个上下相通玻璃球A和B构成,这两个玻璃球都含有一定量的沙子,我们暂且假定AB中位于上方的玻璃球的为U,下方的玻璃球为L,则除非U中没有沙子,否则每秒钟都会有1克沙子从U掉入L。

    在第0个时刻,A中有a克沙子(总共有X克沙子),且U为A,L为B(即A上B下)。在r1,r2,...,rK这些时刻,我们将倒转整个沙漏,使得原来的U变成L,原来的L变成U。

    对于翻转操作,t时刻是指从第0个时刻起经过t秒后的时刻,我们可以将翻转沙漏的操作看做瞬间完成的。

    现在有Q次询问,每一次询问会给定一对非负整数,求a=ai,第ti时刻,A中所含沙子的克数。

    $1leq Xleq 10^9$

    $1leq Kleq 10^5$

    $1leq Qleq 10^5$

    Input

    第一行一个正整数X

    第二行一个正整数K

    第三行K个整数,表示r1,r2,...,rk

    接下来一行一个正整数Q

    接下来Q行,每行两个非负整数,分别表示每次次询问的(ti,ai)

    Output

    一共Q行

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

    题解:

    (别问我为什么拖了两天)

    这个函数要么斜率为1上升,要么斜率为-1下降,碰到上下边界就是一条直线,双指针同时维护翻转和询问,不同的a等同于将图像上下平移,大力模拟即可;

    时间复杂度O(玄学,能过)

    貌似有线段树做法?我不会啊qwq

    代码:

     1 #include<iostream>
     2 #include<cstring>
     3 #include<cstdio>
     4 #include<cmath>
     5 using namespace std;
     6 int X,k,q,t1=0,t2=1,f=-1,maxn,minn=0,now=0,p=0,ans,t[100001],a[100001],r[100001];
     7 int main(){
     8     scanf("%d%d",&X,&k);
     9     for(int i=1;i<=k;i++)scanf("%d",&r[i]);
    10     scanf("%d",&q);
    11     for(int i=1;i<=q;i++)scanf("%d%d",&t[i],&a[i]);
    12     maxn=X;
    13     while(t2<=q){
    14         if(t[t2]>r[t1+1]&&t1<k){
    15             t1++;
    16             now=f*(r[t1]-r[t1-1]);
    17             minn=max(0,min(X,minn+now));
    18             maxn=max(0,min(X,maxn+now));
    19             p+=now;
    20             f*=-1;
    21         }else{
    22             ans=max(minn,min(maxn,a[t2]+p));
    23             ans=max(0,min(X,ans+f*(t[t2]-r[t1])));
    24             printf("%d
    ",ans);
    25             t2++;
    26         }
    27     }
    28     return 0;
    29 }
  • 相关阅读:
    util包的常用类及其方法(下)
    util包的常用类及其方法(上)
    每日一记--java基础01
    每日一记--java细节之问01
    每日一记--设计模式01
    每日一记--JVM虚拟机01
    每日一记--java基础之final/static/事务
    每日一记--Mysql错误代码1067
    每日一记--AOP
    每日一记--代理模式
  • 原文地址:https://www.cnblogs.com/dcdcbigbig/p/9501886.html
Copyright © 2020-2023  润新知