题目传送门
这道题是线段树的一个重要的题型吧(并不清楚重不重要)
要求最后L个数的最大值并不难。
但是他的数是一个一个插进来的。
第一次遇到这种问题可能会蒙蔽。。
首先先建一棵空树就行了。
每次插入的数就相当于在那个位置修改一下值就行。
然后求一求最大值。。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
struct node {
int l,r,lc,rc;
ll c;
}tr[610000];int len;
void bt(int l,int r) {
int now=++len;
tr[now].l=l;tr[now].r=r;
tr[now].lc=tr[now].rc=-1;tr[now].c=0;
if(l<r) {
int mid=(l+r)/2;
tr[now].lc=len+1;bt(l,mid);
tr[now].rc=len+1;bt(mid+1,r);
}
}
void change(int now,int x,ll k) {
if(tr[now].l==tr[now].r) {
tr[now].c=k;return ;
}
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(x<=mid)
change(lc,x,k);
else
change(rc,x,k);
tr[now].c=max(tr[lc].c,tr[rc].c);
}
ll findmax(int now,int l,int r) {
if(tr[now].l==l&&tr[now].r==r)
return tr[now].c;
int lc=tr[now].lc,rc=tr[now].rc,mid=(tr[now].l+tr[now].r)/2;
if(r<=mid)
return findmax(lc,l,r);
else if(l>mid)
return findmax(rc,l,r);
else
return max(findmax(lc,l,mid),findmax(rc,mid+1,r));
}
int main() {
int n;ll mod;
scanf("%d%lld",&n,&mod);
ll t=0;
len=0;bt(1,200000);int trlen=0; //一开始先建一棵空树
for(int i=1;i<=n;i++) {
char s[5];ll x;
scanf("%s %lld",s+1,&x);
if(s[1]=='A')
change(1,++trlen,(x+t)%mod); //每次要插进来数就在那个位置修改值就可以了
else {
t=findmax(1,trlen-x+1,trlen); //同理吧。
printf("%lld\n",t);
}
}
return 0;
}
线段树的强大在于支持修改,log查询。
若查询特别多的话推荐用ST表咯。
O1查询。但是不支持在线修改。
太强了orz!!!