【链接】点击打开链接


【题意】


你有一个沙漏。
沙漏里面总共有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 pdb小结

    Debug功能对于developer是非常重要的,python提供了相应的模块pdb让你可以在用文本编辑器写脚本的情况下进行debug. pdb是python debugger的简称.常用的一些命令如 ...

  2. JS模式

    策略 命令 迭代器 代理 组合 发布/订阅 单例 享元 职责链 中介者 装饰者 状态 适配器 设计原则: 单一职责.最少知识.开放-封闭

  3. 【Python】【Head First Python】【chapter1】1 - 导入模块

    导入模块 导入模块有三种方法,以导入sys模块为例: 第一是import module 形式导入 import sys location = sys.stdout 第二是from module imp ...

  4. Pku3664

    <span style="color:#6600cc;">/* D - Election Time Time Limit:1000MS Memory Limit:655 ...

  5. Chromium Graphics: Android L平台上WebView的变化及其对浏览器厂商的影响分析

    原创文章.转载请以链接形式注明原始出处为http://blog.csdn.net/hongbomin/article/details/40799167. 摘要:Google近期公布的Android L ...

  6. Codeforces Round #262 (Div. 2) 题解

    A. Vasya and Socks time limit per test 1 second memory limit per test 256 megabytes input standard i ...

  7. android5.x加入sim1,sim2标识

    1,mobile_signal_group.xml  ..... <FrameLayout android:id="@+id/mobile_combo" android:la ...

  8. 59.C++与正则表达式

    regex_match 整个字符串是否匹配 (通过cmatch存储匹配的结果),match[0]代表整个匹配序列,match[1]代表第1个匹配后的子序列,match[2]代表第2个匹配后的子序列 代 ...

  9. Linux系统下到哪儿寻找硬件错误

    Linux系统下到哪儿寻找硬件错误       当linux系统出现故障的时候,作为管理员首先要定位错误,现在linux有许多工具都能帮助用户寻找错误,要学会利用他们确定问题.这些工具包括dmesg. ...

  10. 上市公司恋上互联网金融 目前已有14家涌入P2P

    时至今日,互联网金融已蔚然成风,诸多上市公司正前赴后继介入到P2P业务中,据记者初步统计,目前至少有14家A股上市公司参与了P2P业务.央行6月份的报告显示,中国当前有600多家P2P公司,交易额达到 ...