【链接】点击打开链接


【题意】


你有一个沙漏。
沙漏里面总共有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. 00076_BigDecimal

    1.在程序中执行下列代码,会出现什么问题? System.out.println(0.09 + 0.01); System.out.println(1.0 - 0.32); System.out.pr ...

  2. Android学习总结(1)——好的 Android 开发习惯

    Android编码规范 java代码中不出现中文,最多注释中可以出现中文: 局部变量命名.静态成员变量命名:只能包含字母,单词首字母出第一个都为大写,其他字母都为小写: 常量命名:只能包含字母和 ,字 ...

  3. 洛谷—— P2387 魔法森林

    题目描述 为了得到书法大家的真传,小 E 同学下定决心去拜访住在魔法森林中的隐 士.魔法森林可以被看成一个包含 n 个节点 m 条边的无向图,节点标号为 1,2,3,…,n,边标号为 1,2,3,…, ...

  4. POJ 1014 Dividing 背包

    二进制优化,事实上是物体的分解问题. 就是比方一个物体有数量限制,比方是13,那么就须要把这个物体分解为1. 2, 4, 6 假设这个物体有数量为25,那么就分解为1, 2, 4. 8. 10 看出规 ...

  5. 百度地图ios环境配置

    1 前言 由于工作需要,要开始捣腾百度地图了,今天上午初始牛刀,各种碰壁,无奈之下,中午睡了一觉,养精蓄锐,以备下午大战三百回合,所幸下午中午把百度地图Demo捣腾出来了,在此与大家分享,环境搭建教程 ...

  6. vim中使用正則表達式

    一.使用正則表達式的命令 使用正則表達式的命令最常见的就是 / (搜索)命令. 其格式例如以下: /正則表達式 还有一个非常实用的命令就是 :s(替换)命令,将第一个//之间的正則表達式替换成第二个/ ...

  7. AMD规范(RequireJS)、CMD规范(SeaJS)、CommonJS(BravoJS)规范的辨析

    首先,AMD,CMD,CommonJS都实现了文件模块化. 对于依赖的模块:AMD是提前执行:CMD是延迟执行: AMD是依赖前置,CMD是依赖就近: AMD官方解释:https://github.c ...

  8. ZJOI2005沼泽鳄鱼

    矩阵优化dp ** 注意:矩阵乘法没有交换律 ** 思路:类比P2151hh去散步 代码特点在一维的答案矩阵 1.矩阵优化两点间方案数不必赘述 2.注意2,3,4可以办到以他们的lcm为周期,正是因为 ...

  9. userdel---删除用户及相关文件

    userdel命令   userdel命令用于删除给定的用户,以及与用户相关的文件.若不加选项,则仅删除用户帐号,而不删除相关文件. 语法 userdel(选项)(参数) 选项 -f:强制删除用户,即 ...

  10. 多线程编程(二)--进程&amp;&amp;线程

    看完上篇博文的介绍后,大家应该大概了解进程和线程的由来.有了这样一个背景我们进一步来看一下线程和进程. 引入进程: 进程能够提高系统的并发性.提高CPU的使用率,从而提高程序的性能.在曾经单道操作系统 ...