「AHOI2014/JSOI2014」奇怪的计算器
「AHOI2014/JSOI2014」奇怪的计算器
传送门
我拿到这题首先是懵b的,因为感觉没有任何性质。。。
后来经过同机房dalao的指导发现可以把所有的 \(X\) 放到一起排序,然后我们可以发现每次操作都不会改变这个排完序之后的序列的单调性(始终单调不降),也就是说如果其中有一次操作使得数列中的某些数越界了,那么肯定是一个前缀或一个后缀,分别对应向下和向上越界。
然后我们就可以用线段树来搞,每次操作直接用线段树区间修改实现(具体细节待会讲),判断越界的话,我们就存一下区间的最小值和最大值,根据序列单调不降的性质,最小值就是区间左端点的值,最大值就是区间右端点的值,那么我们就可以在线段树上二分+区间赋值来实现批量处理越界的数。
那么接下来就讲一讲区间修改的一种巧妙实现方式:
其实很简单,我们把每次区间修改都写成 \(s_i \leftarrow s_i \times k_1 + a_i \times k_2 + k_3\) 的形式。
那么我们就可以通过调整参数 \(k_1, k_2, k_3\) 的值来很方便地实现区间加法、区间乘法、区间加上 \(a \times x\)、区间赋值的操作了。
参考代码:
#include <algorithm>
#include <cstdio>
#define rg register
#define int long long
#define file(x) freopen(x".in", "r", stdin), freopen(x".out", "w", stdout)
using namespace std;
template < class T > inline void read(T& s) {
s = 0; int f = 0; char c = getchar();
while ('0' > c || c > '9') f |= c == '-', c = getchar();
while ('0' <= c && c <= '9') s = s * 10 + c - 48, c = getchar();
s = f ? -s : s;
}
const int _ = 1e5 + 5;
int n, m, L, R, ans[_]; pair < int, int > a[_];
struct ask { int opt, x; } p[_];
struct node { int mn, mx, tag1, tag2, tag3; } t[_ << 2];
inline int lc(int p) { return p << 1; }
inline int rc(int p) { return p << 1 | 1; }
inline void pushup(int p) { t[p].mn = t[lc(p)].mn, t[p].mx = t[rc(p)].mx; }
inline void f(int p, int l, int r, int tag1, int tag2, int tag3) {
t[p].tag1 = t[p].tag1 * tag1;
t[p].tag2 = t[p].tag2 * tag1 + tag2;
t[p].tag3 = t[p].tag3 * tag1 + tag3;
t[p].mn = t[p].mn * tag1 + a[l].first * tag2 + tag3;
t[p].mx = t[p].mx * tag1 + a[r].first * tag2 + tag3;
}
inline void pushdown(int p, int l, int r, int mid) {
f(lc(p), l, mid, t[p].tag1, t[p].tag2, t[p].tag3);
f(rc(p), mid + 1, r, t[p].tag1, t[p].tag2, t[p].tag3);
t[p].tag1 = 1, t[p].tag2 = t[p].tag3 = 0;
}
inline void build(int p = 1, int l = 1, int r = m) {
t[p].tag1 = 1, t[p].tag2 = t[p].tag3 = 0;
if (l == r) { t[p].mn = t[p].mx = a[l].first; return ; }
int mid = (l + r) >> 1;
build(lc(p), l, mid), build(rc(p), mid + 1, r), pushup(p);
}
inline void update_mn(int p = 1, int l = 1, int r = m) {
if (l == r) { f(p, l, r, 0, 0, L); return ; }
int mid = (l + r) >> 1;
pushdown(p, l, r, mid);
if (t[rc(p)].mn < L) f(lc(p), l, mid, 0, 0, L), update_mn(rc(p), mid + 1, r);
else update_mn(lc(p), l, mid);
pushup(p);
}
inline void update_mx(int p = 1, int l = 1, int r = m) {
if (l == r) { f(p, l, r, 0, 0, R); return ; }
int mid = (l + r) >> 1;
pushdown(p, l, r, mid);
if (t[lc(p)].mx > R) f(rc(p), mid + 1, r, 0, 0, R), update_mx(lc(p), l, mid);
else update_mx(rc(p), mid + 1, r);
pushup(p);
}
inline void query(int p = 1, int l = 1, int r = m) {
if (l == r) { ans[a[l].second] = t[p].mn; return ; }
int mid = (l + r) >> 1;
pushdown(p, l, r, mid);
query(lc(p), l, mid), query(rc(p), mid + 1, r);
}
inline int cg(char c) {
if (c == '+') return 1; if (c == '-') return 2; if (c == '*') return 3; if (c == '@') return 4;
}
signed main() {
#ifndef ONLINE_JUDGE
file("cpp");
#endif
read(n), read(L), read(R);
char s[5];
for (rg int x, i = 1; i <= n; ++i) scanf("%s", s), read(x), p[i] = (ask) { cg(s[0]), x };
read(m);
for (rg int x, i = 1; i <= m; ++i) read(x), a[i] = make_pair(x, i);
sort(a + 1, a + m + 1), build();
for (rg int i = 1; i <= n; ++i) {
if (p[i].opt == 1) f(1, 1, m, 1, 0, p[i].x);
if (p[i].opt == 2) f(1, 1, m, 1, 0, -p[i].x);
if (p[i].opt == 3) f(1, 1, m, p[i].x, 0, 0);
if (p[i].opt == 4) f(1, 1, m, 1, p[i].x, 0);
if (t[1].mn < L) update_mn();
if (t[1].mx > R) update_mx();
}
query();
for (rg int i = 1; i <= m; ++i) printf("%d\n", ans[i]);
return 0;
}
「AHOI2014/JSOI2014」奇怪的计算器的更多相关文章
- 「AHOI2014/JSOI2014」宅男计划
「AHOI2014/JSOI2014」宅男计划 传送门 我们首先要发现一个性质:存货天数随买食物的次数的变化类似于单峰函数. 具体证明不会啊,好像是二分加三分来证明?但是没有找到明确的严格证明. 感性 ...
- 「AHOI2014/JSOI2014」拼图
「AHOI2014/JSOI2014」拼图 传送门 看到 \(n \times m \le 10^5\) ,考虑根号分治. 对于 \(n < m\) 的情况,我们可以枚举最终矩形的上下边界 \( ...
- 「AHOI2014/JSOI2014」骑士游戏
「AHOI2014/JSOI2014」骑士游戏 传送门 考虑 \(\text{DP}\). 设 \(dp_i\) 表示灭种(雾)一只编号为 \(i\) 的怪物的代价. 那么转移显然是: \[dp_i ...
- 「AHOI2014/JSOI2014」支线剧情
「AHOI2014/JSOI2014」支线剧情 传送门 上下界网络流. 以 \(1\) 号节点为源点 \(s\) ,新建一个汇点 \(t\),如果 \(u\) 能到 \(v\),那么连边 \(u \t ...
- #3144. 「APIO 2019」奇怪装置
#3144. 「APIO 2019」奇怪装置 题目描述 考古学家发现古代文明留下了一种奇怪的装置.该装置包含两个屏幕,分别显示两个整数 \(x\) 和 \(y\). 经过研究,科学家对该装置得出了一个 ...
- 「UNR#1」奇怪的线段树
「UNR#1」奇怪的线段树 一道好题,感觉解法非常自然. 首先我们只需要考虑一次染色最下面被包含的那些区间,因为把无解判掉以后只要染了一个节点,它的祖先也一定被染了.然后发现一次染色最下面的那些区间一 ...
- 【LOJ #3144】「APIO 2019」奇怪装置
题意: 定义将一个\(t\)如下转换成一个二元组: \[ f(t) = \begin{cases} x = (t + \left\lfloor \frac{t}{B} \right \rfloor) ...
- 「APIO 2019」奇怪装置
题目 考虑推柿子 最开始的想法是如果两个\(t\)在\(mod\ B\)意义下相等,那么只需要比较一下\((t+\left \lfloor \frac{t}{B}\rfloor \right)mod\ ...
- BZOJ3878: [Ahoi2014&Jsoi2014]奇怪的计算器
BZOJ3878: [Ahoi2014&Jsoi2014]奇怪的计算器 Description [故事背景] JYY有个奇怪的计算器,有一天这个计算器坏了,JYY希望你能帮助他写 一个程序来模 ...
随机推荐
- 工具 - deepin vscode中的oh-my-zsh乱码
解决办法 https://blog.zhaytam.com/2019/04/19/powerline-and-zshs-agnoster-theme-in-vs-code/ git clone htt ...
- Caffe 笔记 (一)caffe的层与数据结构
Caffe是纯粹的C++/CUDA架构,支持命令行.Python和MATLAB接口:可以在CPU和GPU直接无缝切换: Caffe::set_mode(Caffe::GPU); Caffe的优势 1. ...
- Android学习10
SharedPreferences 今天练习了利用SharedPreferences保存登录用户名密码: layout布局: <?xml version="1.0" enco ...
- Codeforces Round #624 (Div. 3) F
题意: 给出n的质点,带着初位置和速度: 如果中途两点可以相遇dis(i,j)=0: 如果不可以相遇,mindis(i,j): 求n个点的两两质点最小dis(i,j)之和 思路: 因为当初位置x和速度 ...
- 对于使用secureFX上传文件到centos7 的时候,以及不同的用户解压文件,对于文件操作权限的实验
本以为以一个用户胡如root登录了SecureFx,之后选择了root的家目录下的一个software目录,之后上传 以root用户远程登录LINUX系统 查看文件 之后再验证普通用户zhaijh登录 ...
- NTP网络授时服务器部署及网络时钟同步设置说明
NTP网络授时服务器部署及网络时钟同步设置说明 NTP网络授时服务器部署及网络时钟同步设置说明 本文由安徽京准科技提供@请勿转载. 一.前言 1.NTP简介 NTP是网络时间协议(Network T ...
- linux使用wget下载https开头url的文件
可以使用命令 : 比如我们可以修改成: wget --no-check-certificate https://我们下载文件路径 来自: http://www.laozuo.org/3648.html
- Bugku-CTF加密篇之一段Base64
一段Base64 flag格式:flag{xxxxxxxxxxxxx}
- Vue——项目中接口返回值为函数回调,回调函数定义方法(Vue的方法给原生调用)
在接口调用中,有时会返回给我们一个函数回调,来自动执行我们在前端定义好的某个函数(多出现于通过回调的方式传递某个数值).在原生项目中,我们只要提供一下这个方法就好了,通过函数回调会自动执行.问题就出现 ...
- 【MySQL】常用增删改查
目录 1. 文件夹(库) 2. 文件(表) 3. 文件内容(数据) "@ ___ 1. 文件夹(库) # 增 create database db charset utf8; # 查 sho ...