【链接】点击打开链接


【题意】


你有一个沙漏。
沙漏里面总共有X单位的沙子.
沙漏分A,B上下两个部分。
沙漏从上半部分漏沙子到下半部分。
每个时间单位漏1单位的沙子。
一开始A部分在上面。然后在r1,r2,....rk时刻,会把沙漏翻转一下.
给你Q个询问,每个询问两个数字ti,ai;
表示一开始A部分有ai个单位的沙子,问你ti时刻,A部分有多少沙子。

【题解】


我们设f[i]表示初始A部分有i个单位的沙子,t时刻A中剩余的沙子数目,并假设X=7;
我们先来模拟一下这个过程,右边的加号和减号表示沙子增加或减少(对应A在漏或在接沙子)
t=0 f[] = {0,1,2,3,4,5,6,7}
t=1 f[] = {1,2,3,4,5,6,7,7} +
t=2 f[] = {2,3,4,5,6,7,7,7} +
t=3 f[] = {3,4,5,6,7,7,7,7} +
t=4 f[] = {2,3,4,5,6,6,6,6} -
t=5 f[] = {1,2,3,4,5,5,5,5} -
t=6 f[] = {0,1,2,3,4,4,4,4} -
t=7 f[] = {0,0,1,2,3,3,3,3} -
t=8 f[] = {1,1,2,3,4,4,4,4} +
可以看到,f数组总是类似{a,a,a+1,a+2,a+3...b-2,b-1,b,b}这样的形式;
a和b会随着沙子减少或增加的时候发生改变.
而且变化都是有规律的,因为每个数字都递增1或递减1.
那么,如果我们能维护a和b的位置l和r的话,就能很容易得到答案了.
如果初始沙子ai<=l,则答案为a,如果ai >= r则答案为b,否则为a + ai - l;
我们可以按照ri的时间,一块一块地获取到ri时刻f数组的四个参数a,b,l,r;
(因为r[i-1]..r[i]这一段肯定都是减,或都是加,那么想要维护a,b,l,r就不会难了)
(只有在a减去时间差小于0或是b加上时间差大于X的时候,l和r才会变)
然后对于询问ti,ai,我们只要找到最大的j,使得rj <= ti;
这样,我们先通过rj时刻f数组的参数a,b,l,r来获取初始沙子量为ai,rj时刻A的沙子量temp.
然后rj..ti这一段则全是减或全是加,则temp直接加上或减去ti-rj就可以了,大于X则变成X,小于0则变成0.
做的时候,可以把询问和翻转操作的时间放在一起,然后排个序.
翻转操作,就维护a,b,l,r;如果是询问操作,就通过a,b,l,r求出初始沙子量为ai,时刻前一个翻转点A的沙子量temp.
再加上ti-前一个反转点的时间就是所需的答案了。


【错的次数】


1

【反思】


初始沙子量为0..X;
然后时间为t时,对应沙子量随着t的递增,是有规律的.
因为每种初始沙子量,它随着时间,在某个区间内都是递增1,或都是递减1.
这样,在整块都是递减,或整块都是递增的时间里,我们能快速维护,初始沙子量为0..X,对应时间的沙子量.
(不用求出来,只要通过维护4个变量就能O(1)处理询问);
虽然询问是单点的.
但只要能快速求出它前一个翻转的时间点,剩下的也能O(1)处理.
翻转的时间点之间就是整块的加或整块减的时间。
如果只有一个初始的沙子量,那么这题就是一道水题了。
但是因为多个沙子量,给实现造成了很大的困难.
因此通过模拟,发现初始沙子量不同的话,到某个时刻的沙子量是有规律的。
从而解决了有多个初始沙子量的问题。

【代码】

/*

*/
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <vector>
#include <map>
#include <queue>
#include <iomanip>
#include <set>
#include <cstdlib>
#include <cmath>
#include <bitset>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define LL long long
#define rep1(i,a,b) for (int i = a;i <= b;i++)
#define rep2(i,a,b) for (int i = a;i >= b;i--)
#define mp make_pair
#define pb emplace_back
#define fi first
#define se second
#define ld long double
#define ms(x,y) memset(x,y,sizeof x)
#define ri(x) scanf("%d",&x)
#define rl(x) scanf("%lld",&x)
#define rs(x) scanf("%s",x)
#define rf(x) scnaf("%lf",&x)
#define oi(x) printf("%d",x)
#define ol(x) printf("%lld",x)
#define oc putchar(' ')
#define os(x) printf(x)
#define all(x) x.begin(),x.end()
#define Open() freopen("F:\\rush.txt","r",stdin)
#define Close() ios::sync_with_stdio(0)
#define sz(x) ((int) x.size())
#define ld long double typedef pair<int,int> pii;
typedef pair<LL,LL> pll; //mt19937 myrand(time(0));
//int get_rand(int n){return myrand()%n + 1;}
const int dx[9] = {0,1,-1,0,0,-1,-1,1,1};
const int dy[9] = {0,0,0,-1,1,-1,1,-1,1};
const double pi = acos(-1.0);
const int N = 2e5; struct abc{
    int t,a,id;
    bool operator < (const abc & tmp) const{
        return t < tmp.t;
    }
}; int X,K,n,ans[N+10];
abc q[N+10]; int main(){
    //Open();
    //Close();
    ri(X),ri(K);
    rep1(i,1,K) {
        int x;
        ri(x);
        q[++n].t = x;
    }
    ri(K);
    rep1(i,1,K){
        int t,a;
        ri(t),ri(a);
        q[++n].t = t,q[n].a = a,q[n].id = i;
    }
    sort(q+1,q+1+n);
    int a = 0,b = X,l = 0,r = X,pre = 0,sign = -1;
    rep1(i,1,n)
        if (q[i].id){
            //是一个询问
            int rest = q[i].t - pre,temp;
            if (q[i].a <= l){
                temp = a;
            }else if (q[i].a >= r){
                        temp = b;
                  }else
                        temp = a + q[i].a - l;
            temp += sign*rest;
            if (temp > X) temp = X;
            if (temp < 0) temp = 0;
            ans[q[i].id] = temp;
        }else{
            //是一个翻转操作
            int v = q[i].t - pre;
            if (sign==-1){//如果要做减法
                if (a<v){//如果最小的那个不够减了,则肯定
                    b = max(b-v,0);
                    l = min(l + (v-a),X);
                    r = max(l,r);
                    a = 0;
                }else{
                    a-=v,b-=v;
                }
            }else{
                if (b+v<=X){//最大的加上v之后都小于等于X则可行,a+v<=x,a+1+v<=x...a+b-a+v<=x
                    a+=v,b+=v;
                }else{
                    //b+v>X
                    a = min(a+v,X);//a加上之后可能大于X了.最大让他为X
                    r = max(r - (b+v-X),0);//倒数第1+(b+v-X)个数到最后一个数都变成X了
                    l = min(l,r);//r要是小于l了,就把l变成r就好.
                    b = X;//b是肯定变成x了
                }
            }
            pre = q[i].t;
            sign = sign*(-1);
        }
    rep1(i,1,K)
        oi(ans[i]),puts("");
    return 0;
}

【AtCoder Regular Contest 082 F】Sandglass的更多相关文章

  1. 【AtCoder Regular Contest 082 A】Together

    [链接]点击打开链接 [题意] 给你n个数字,每个位置上的数字可以+1,不变,或-1,每个位置只能操作一次. 操作完之后,让你选一个数字x,然后统计a[i]==x的个数count. 问你count的最 ...

  2. 【AtCoder Regular Contest 076 F】Exhausted (贪心)

    Description 机房里有M台电脑排成一排,第i台电脑的坐标是正整数i. 现在有N个OIer进入了机房,每个OIer需要一台电脑来学tui习ji,同时每个OIer对自己电脑所处的坐标范围有一个要 ...

  3. 【推导】【模拟】AtCoder Regular Contest 082 F - Sandglass

    题意:有个沙漏,一开始bulb A在上,bulb B在下,A内有a数量的沙子,每一秒会向下掉落1.然后在K个时间点ri,会将沙漏倒置.然后又有m个询问,每次给a一个赋值ai,然后询问你在ti时刻,bu ...

  4. 【AtCoder Regular Contest 082】Derangement

    [链接]点击打开链接 [题意] 在这里写题意 [题解] 贪心. 连续一块的p[i]==i的话,对答案的贡献就应该为(这个连续块的长度+1)/2; 长度为1的也正确. (也即两两相邻的互换位置.) [错 ...

  5. AtCoder Regular Contest 082 F

    Problem Statement We have a sandglass consisting of two bulbs, bulb A and bulb B. These bulbs contai ...

  6. 【Atcoder Grand Contest 011 F】Train Service Planning

    题意:给\(n+1\)个站\(0,\dots,n\),连续的两站\(i-1\)和\(i\)之间有一个距离\(A_i\),其是单行(\(B_i=1\))或双行(\(B_i=2\)),单行线不能同时有两辆 ...

  7. AtCoder Regular Contest 069 F Flags 二分,2-sat,线段树优化建图

    AtCoder Regular Contest 069 F Flags 二分,2-sat,线段树优化建图 链接 AtCoder 大意 在数轴上放上n个点,点i可能的位置有\(x_i\)或者\(y_i\ ...

  8. AtCoder Regular Contest 082 D Derangement

    AtCoder Regular Contest 082 D Derangement 与下标相同与下个交换就好了.... Define a sequence of ’o’ and ’x’ of lengt ...

  9. Atcoder Regular Contest 066 F genocide【JZOJ5451】

    题目 分析 \(s[i]\)表示a前缀和. 设\(f[i]\)表示做完了1~i的友谊颗粒的最优值(不一定选i),那么转移方程为 \[f[i]=max\{f[i-1],max\{f[j]-s[i]+s[ ...

随机推荐

  1. 树莓派开机运行Python脚本 控制LED灯闪烁

    一.新建一个开机运行文件 在 /home/pi/.config 下创建一个文件夹,名称为 autostart,并在该文件夹下创建一个led.desktop文件(文件名以.desktop结尾) 编辑le ...

  2. HDU4596 Yet another end of the world 扩展欧几里德性质

    这题坑了,我真该吃翔啊,竟然一開始方程设错了并且没有去想连列的问题,我真是坑货,做不出就该又一次理一下嘛.操蛋. 题意:给了N组x,y,z然后 问你是否存在两个或者两个以上的id,是的 id%x的值在 ...

  3. 杭电5137How Many Maos Does the Guanxi Worth

    How Many Maos Does the Guanxi Worth Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 512000/5 ...

  4. Linux下Oracle的sqlplus中上下左右退格键无法使用

    一.配置yum源并安装readline* 配置本地yum 1.挂载光盘 mount /dev/cdrom /mnt/media 2,新建本地yun源的配置文件 vi /etc/yum.repos.d/ ...

  5. OpenCASCADE中散乱Edge生成Wire

    OpenCASCADE中散乱Edge生成Wire eryar@163.com Abstract. In OpenCASCADE a wire can be built from any number ...

  6. Scott Hanselman的问题-3

    .Net程序员面试 中级篇 (回答Scott Hanselman的问题)   继<.Net 程序员面试 C# 语言篇 (回答Scott Hanselman的问题)>跟<.Net程序员 ...

  7. 43.安装npm及cnpm(Windows)

    转自:https://www.cnblogs.com/yominhi/p/7039795.html [工具官网] Node.js : http://nodejs.cn/ 淘宝NPM: https:// ...

  8. html --- rem 媒体查询

    rem是一种相对长度单位,参考的基准是<html>标签定义的font-size. viewport 做移动端的h5,通常会在HTML文件中指定一个<meta>标签: <m ...

  9. ElasticSearch 在Hadoop生态圈的位置

    它的位置非常清晰,直接贴图. 更详细点,见

  10. VS Code 关于SFTP上传文件到多服务器的配置

    工欲善其事,必先利其器! 刚学前端的时候一直用的DW来编写代码,其功能非常强大,但在Linux下不能用,所以就转VS Code了. 但是刚开始使用VS Code的时候,很多DW上的功能需要自己安装扩展 ...