线段树:
直接就是标准模板,先直接建立一个长度为2e5的线段树,然后单点修改,区间查值。
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N = 2e5 + 10;
#define l(x) t[x].l
#define r(x) t[x].r
#define ans(x) t[x].ans
struct SegmenTree{
int l,r,ans = -2e9;
}t[N*4];
int n,m,d,last;
void push_up(int p){
ans(p) = max(ans(p*2),ans(p*2+1));
}
void build(int p,int l,int r){
l(p) = l,r(p) = r;
if(l == r) return ;
int mid = (l + r) >> 1;
build(p*2,l,mid);build(p*2+1,mid+1,r);
}
void update(int p,int x,int d){
if(l(p) == r(p)){
ans(p) = d;
return ;
}
int mid = (l(p) + r(p)) >> 1;
if(x <= mid) update(p*2,x,d);
else update(p*2+1,x,d);
push_up(p);
}
int ask(int p,int l,int r){
if(l <= l(p) && r >= r(p)) return ans(p);
int val = -2e9;
int mid = (l(p) + r(p)) >> 1;
if(l <= mid) val = max(val,ask(p*2,l,r));
if(r > mid) val = max(val,ask(p*2+1,l,r));
return val;
}
int main(){
cin>>m>>d;
build(1,1,N);
while(m --){
char s; int p; cin>>s>>p;
if(s == 'A'){
n++;
int k = (p+last)%d;
update(1,n,k);
}else{
last = ask(1,n-p+1,n);
cout<<last<<endl;
}
}
return 0;
}
单调栈 + 二分
建立一个单调下降的栈,因为只需要后面的最大值,所以去除前面小的毫无影响。
之后二分查找下表在询问区间且最小的那个元素。因为构建的是单调下降的栈。
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
const int N = 2e5 + 10;
int st[N],top=-1;
int a[N],last,m,d,n;
void update(int x,int id){
while(top != -1 && a[st[top]] < x) --top;
st[++top] = id;
}
int ask(int res,int l,int r){
while(l < r){
int mid = (l + r) >> 1;
if(st[mid] < res) l = mid + 1;
else r = mid;
}
return a[st[r]];
}
int main(){
cin>>m>>d;
while(m --){
char s; int p; cin>>s>>p;
if(s == 'A'){
a[++n] = (p+last)%d;
update(a[n],n);
}else{
last = ask(n-p+1,0,top);
cout<<last<<endl;
}
}
return 0;
}
单调栈+并查集
并查集的作用就是记录把当前这个元素抵消的是哪个值。前面再大也不会影响当前的父节点。查询最左端点抵消它的父节点是哪个即可。
#include<iostream>
#include<algorithm>
#include<stack>
using namespace std;
const int N = 2e5 + 10;
int st[N],top=-1;
int a[N],last,m,d,n,fa[N];
void update(int x,int id){
while(top != -1 && a[st[top]] < x){
fa[st[top]] = id;
--top;
}
st[++top] = id;
}
int find(int x){
if(x != fa[x]) fa[x] = find(fa[x]);
return fa[x];
}
int ask(int x){
return a[find(x)];
}
int main(){
cin>>m>>d;
while(m --){
char s; int p; cin>>s>>p;
if(s == 'A'){
a[++n] = (p+last)%d;
fa[n] = n;
update(a[n],n);
}else{
last = ask(n-p+1);
cout<<last<<endl;
}
}
return 0;
}