Sandglass(模拟分段函数)

问题 I: Sandglass

时间限制: 1 Sec  内存限制: 128 MB
提交: 244  解决: 44
[提交] [状态] [讨论版] [命题人:admin]

题目描述

We have a sandglass consisting of two bulbs, bulb A and bulb B. These bulbs contain some amount of sand. When we put the sandglass, either bulb A or B lies on top of the other and becomes the upper bulb. The other bulb becomes the lower bulb.
The sand drops from the upper bulb to the lower bulb at a rate of 1 gram per second. When the upper bulb no longer contains any sand, nothing happens.
Initially at time 0, bulb A is the upper bulb and contains a grams of sand; bulb B contains X−a grams of sand (for a total of X grams).
We will turn over the sandglass at time r1,r2,..,rK. Assume that this is an instantaneous action and takes no time. Here, time t refer to the time t seconds after time 0.
You are given Q queries. Each query is in the form of (ti,ai). For each query, assume that a=ai and find the amount of sand that would be contained in bulb A at time ti.

Constraints
1≤X≤109
1≤K≤105
1≤r1<r2<..<rK≤109
1≤Q≤105
0≤t1<t2<..<tQ≤109
0≤ai≤X(1≤i≤Q)
All input values are integers.

样例输入

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

样例输出

60
1
120

给你一个沙漏,告诉你沙漏里有多少沙子(同时这也是沙漏的上部分或下部分的容积),然后告诉你会进行k次翻转的时刻点(递增)

q次询问,问在初始值为ai的时候第t秒a部分(最开始是上半部分)里沙子的质量(t递增)

扫描二维码关注公众号,回复: 2505465 查看本文章

一开始觉得很简单,觉得可以模拟但可能超时,然后就写了下面这个代码,果然超时

#include<bits/stdc++.h>
using namespace std;
int tim[100005];
int ans[100005];
int main()
{
    int x;
    int k;
    scanf("%d%d",&x,&k);
 
    for(int i=0;i<k;i++)
        scanf("%d",&tim[i]);
 
    int q;
    scanf("%d",&q);
    for(int i=0;i<q;i++)
    {
        int t,ai;
        scanf("%d%d",&t,&ai);
 
        int flag = -1;
        int j;
        for(j=0;tim[j]<t;j++)
        {
            ai = ai+flag*(j==0?tim[j]:tim[j]-tim[j-1]);
            if(ai>x)
                ai=x;
            if(ai<0)
                ai=0;
            flag*=-1;
            //printf("--%d\n",ai);
        }
        ai = ai+flag*(t-tim[j-1]);
        if(ai>x)
            ai=x;
        if(ai<0)
            ai=0;
        printf("%d\n",ai);
 
    }
 
    return 0;
}

但是实际上应该这样想,可以模拟t秒时a部分所有的ai初始值的情况(也就是0---x),这样每次询问的时候再考虑这次输入的ai就可以了(因为询问的时间依次递增)

那么实际上可以得到一条曲线设x轴为ai的初始值,y轴为t秒后的a部分里的沙子质量,那么,

一开始,曲线就是个正比例函数(并且斜率是1),每过一秒,曲线向下(上 )平移一个单位,注意

移动后不能小于零,不能大于x,这样最多变成一个三段的分段函数,那么维护两个分界点即可

add是如果什么都不考虑,原图像的平移量,那么加上ai再mix(我写的一个函数,用来限制范围)一下就得到了当前的值,

因为t不一定是恰好在翻转点,那么要加上flag*(t-tim[j-1]),再限制在0----x之间就是答案了

#include<bits/stdc++.h>
using namespace std;
int tim[100005];
int x,k,q;
int mix(int t,int l = 0,int r = x) {
    return t>r?r :(t<l?l:t);
}
int main()
{
    scanf("%d%d",&x,&k);
 
    for(int i=0;i<k;i++)
        scanf("%d",&tim[i]);
 
    scanf("%d",&q);
    int j = 0;
    int up,low,add = 0,flag = -1;
    up = x,low = 0;
    for(int i=0;i<q;i++)
    {
        int t,ai;
        scanf("%d%d",&t,&ai);
 
        while(j<k&&tim[j]<=t)
        {
            int c = flag*(j==0?tim[j]:tim[j]-tim[j-1]);
            add += c;
            up = mix(up+c);
            low = mix(low+c);
            flag*=-1;
            j++;
        }
        ai = mix(flag*(t-tim[j-1])+mix(ai+add,low,up));
        printf("%d\n",ai);
    }
 
    return 0;
}

猜你喜欢

转载自blog.csdn.net/du_mingm/article/details/81279088