BZOJ 1012 [JSOI2008]最大数maxnumber
题目链接:BZOJ 1012 [JSOI2008]最大数maxnumber 洛谷 P1198 [JSOI2008]最大数
算法标签: 线段树
题目
题目描述
现在请求你维护一个数列,要求提供以下两种操作:1、 查询操作。语法:Q L 功能:查询当前数列中末尾L
个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。2、 插入操作。语法:A n 功能:将n加
上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取
模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个
数。
输入格式
第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足D在longint内。接下来
M行,查询操作或者插入操作。
输出格式
对于每一个询问操作,输出一行。该行只有一个数,即序列中最后L个数的最大数。
输入输出样例
输入 #1
5 100
A 96
Q 1
A 97
Q 1
Q 2
输出 #1
96
93
96
题解:
线段树
线段树维护区间最值 + 单点修改。
由于这道题十分优秀毒瘤的修改方式,我们需要对于每次询问都记下当前询问的值,因为下一次修改又会用到。同时我们又要记录修改次数(当前点),同样修改对于询问也是有贡献的,所以我们需要在cnt
和pr
之间来回操作,那么主函数中对于这部分的处理代码如下:
if (c == 'A') {
int x = rd();
cnt ++ ;
x = (x + pr) % mod;
fix(1, 1, m, cnt, x);
}
else {
int x = rd();
pr = query(1, 1, m, cnt - x + 1, cnt);
printf("%d
", pr);
}
其他的就是线段树的修改、查询模板,直接套用即可。这里手写了一下宏定义的Max
据说会快!!!
修改:
void fix(int pos, int l, int r, int id, int val) {
int mid = (l + r) >> 1;
if (l == r) {
tree[pos] = val;
return ;
}
if (id <= mid) {
fix(lson, l, mid, id, val);
}
else {
fix(rson, mid + 1, r, id, val);
}
tree[pos] = Max(tree[lson], tree[rson]);
}
查询:
int query(int pos, int l, int r, int x, int y) {
if (x <= l && r <= y) {
return tree[pos];
}
int mid = (l + r) >> 1;
int ans = 0;
if (x <= mid) {
ans = max(ans, query(lson, l, mid, x, y));
}
if (mid < y) {
ans = max(ans, query(rson, mid + 1, r, x, y));
}
return ans;
}
对了不要忘记最开始需要把tree[]
数组赋一个极小值!!!!
AC代码
#include <bits/stdc++.h>
#define lson pos << 1
#define rson pos << 1 | 1
#define Max(x, y) ((x) > (y) ? (x) : (y))
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int N = 200020;
char s[10];
ll tree[N * 4], mod;
int m, cnt, pr;
char *p1, *p2, buf[100000];
#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )
int rd() {
int x = 0, f = 1;
char c = nc();
while (c < 48) {
if (c == '-')
f = -1;
c = nc();
}
while (c > 47) {
x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
}
return x * f;
}
ll rd2() {
ll x = 0;
char c = nc();
while (c < 48) {
c = nc();
}
while (c > 47) {
x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
}
return x;
}
void fix(int pos, int l, int r, int id, int val) {
int mid = (l + r) >> 1;
if (l == r) {
tree[pos] = val;
return ;
}
if (id <= mid) {
fix(lson, l, mid, id, val);
}
else {
fix(rson, mid + 1, r, id, val);
}
tree[pos] = Max(tree[lson], tree[rson]);
}
int query(int pos, int l, int r, int x, int y) {
if (x <= l && r <= y) {
return tree[pos];
}
int mid = (l + r) >> 1;
int ans = 0;
if (x <= mid) {
ans = max(ans, query(lson, l, mid, x, y));
}
if (mid < y) {
ans = max(ans, query(rson, mid + 1, r, x, y));
}
return ans;
}
int main() {
memset(tree, -inf, sizeof tree);
m = rd(), mod = rd2();
for (int i = 1; i <= m; i ++ ) {
char c = nc();
while (c != 'A' && c != 'Q') {
c = nc();
}
if (c == 'A') {
int x = rd();
cnt ++ ;
x = (x + pr) % mod;
fix(1, 1, m, cnt, x);
}
else {
int x = rd();
pr = query(1, 1, m, cnt - x + 1, cnt);
printf("%d
", pr);
}
}
return 0;
}