BZOJ 1012 [JSOI2008]最大数maxnumber - 线段树

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

题解:

线段树

线段树维护区间最值 + 单点修改。

由于这道题十分优秀毒瘤的修改方式,我们需要对于每次询问都记下当前询问的值,因为下一次修改又会用到。同时我们又要记录修改次数(当前点),同样修改对于询问也是有贡献的,所以我们需要在cntpr之间来回操作,那么主函数中对于这部分的处理代码如下:

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\n", 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\n", pr);
        }
    }
    return 0;
}
posted @ 2019-11-12 14:29  筱柒_Littleseven  阅读(108)  评论(0编辑  收藏  举报