洛谷 P1198 [JSOI2008]最大数

题目链接

如果还没看题目的可以先去看一下题目

前置知识线段树

这个题目就是两个操作,一个是添加数据,一个是查询区间最大值,但是由于数据范围达到1e5,所以我直接想到的就是线段树了,下面我们来看看线段树要怎么做。

首先是建树,由于题目中的数据有负数负数负数,所以大家建树的时候一定要注意!!!初始化权值和懒人标记为-(1<<62)。

然后是更新,这个就和普通的线段树更新一样,需要用到懒人标记的时候就向下更新懒人标记。

最后是查询,也和模板线段树一样,遇到要更新懒人标记的时候及时更新懒人标记就好了。

上代码!!!

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#include<map>
#define ll long long
#define pi acos(-1)
#define pii pair<int, int>
#define fi first
#define se second
#define mp(a, b) make_pair(a, b)
#define piii pair<pii, int>
#define uf(a, b, i) for (register int i = (a); i <= (b); ++i)
#define df(a, b, i) for (register int i = (a); i >= (b); --i)
using namespace std;
inline ll read() {
	ll x = 0, f = 1;
	char ch = getchar();
	while(ch < '0' || ch > '9') {
		if(ch == '-') f = -1;
		ch = getchar();
	}
	while(ch >= '0' && ch <= '9') {
		x = x * 10 + ch - '0';
		ch = getchar();
	}
	return x * f;
}
template<class T>
inline void print(T x) {
	if(x > 9) print(x/10);
	putchar(x%10 + '0');
}
template<class T>
T Max(T a, T b) {
  return a > b ? a : b;
}
template<class T>
T Min(T a, T b) {
  return a < b ? a : b;
}
const ll mod = 1e9 + 7;
const ll inf = -4611686018427387904;//-(1<<62)
ll ans;
int p;
struct Tree {
  int l, r;
  ll val, lazy;
} tree[800005];
void build(int node, int l, int r) {
  tree[node].val = inf; tree[node].lazy = inf;
  tree[node].l = l; tree[node].r = r;
  if (l == r) return ;
  build(node<<1, l, l+r>>1);
  build(node<<1|1, (l+r>>1)+1, r);
}
void down(int node) {
  tree[node<<1].lazy = Max(tree[node<<1].lazy, tree[node].lazy);
  tree[node<<1].val = Max(tree[node<<1].val, tree[node].lazy);
  
  tree[node<<1|1].lazy = Max(tree[node<<1|1].lazy, tree[node].lazy);
  tree[node<<1|1].val = Max(tree[node<<1|1].val, tree[node].lazy);
  
  tree[node].lazy = inf;
}
void update(int node, int l, int r, ll val) {
  if (1 <= tree[node].l && tree[node].r <= r) {
    tree[node].val = Max(tree[node].val, val);
    tree[node].lazy = Max(tree[node].lazy, val);
    return ;
  } else {
    down(node);
    if ((tree[node].l + tree[node].r >> 1) >= l) update(node<<1, l, r, val);
    if ((tree[node].l + tree[node].r >> 1) < r) update(node<<1|1, l, r, val);
    tree[node].val = Max(tree[node<<1].val, tree[node<<1|1].val);
  }
}
void ask(int node, int l, int r) {
  if (tree[node].l >= l && tree[node].r <= r) {
    ans = Max(ans, tree[node].val);
    return ;
  } else {
    down(node);
    if ((tree[node].l + tree[node].r >> 1) >= l) ask(node<<1, l, r);
    if ((tree[node].l + tree[node].r >> 1) < r) ask(node<<1|1, l, r);
  }
}
int n, m, t, cnt;
int a[200005];
void scan() {
  n = read(); p = read();
}
void work() {
  build(1, 1, n);
  uf (1, n, i) {
    char c;
    int val;
    cin >> c >> val;
    if (c == 'A') {
      update(1, 1, ++cnt, (val+t)%p);
    } else {
      ans = inf;
      ask(1, cnt-val+1, cnt);
      cout << ans << endl;
      t = ans;
    }
  }
}
int main() {
	scan();
	work();
	return 0;
}
/*
5 100
A -10
Q 1
A 5
Q 1
Q 2
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值