洛谷P1198:https://www.luogu.org/problemnew/show/P1198
思路
一道水水的线段树 20分钟A掉
这道题只涉及到单点修改和区间查询 所以这道题甚至不用Lazy-Tag
每次加入一个新的点就是修改一个节点
总区间长为操作次数m (假设所有操作都为添加一个节点)
因此题目就简单多了
代码
#include<iostream> using namespace std; #define ll long long #define Max 200000 #define INF 1e9+7 ll m,p,n,t; ll maxn[Max<<2];//4倍数组 void build(ll s,ll v,ll l,ll r,ll k) { if(l==r) { maxn[k]=v;//叶子节点 return; } ll mid=(l+r)>>1; if(mid>=s) build(s,v,l,mid,k<<1);//当此点在mid前 只需要建mid前面的树 if(mid<s) build(s,v,mid+1,r,k<<1|1);//同上 maxn[k]=max(maxn[k<<1],maxn[k<<1|1])%p; return; } ll query(ll x,ll y,ll l,ll r,ll k) { if(l>=x&&r<=y) return maxn[k]%p; ll mid=(l+r)>>1; ll a1=-INF,b1=-INF;//因为有负数 所以要设一个负的极小值 if(x<=mid) a1=query(x,y,l,mid,k<<1)%p;//左子树的最大值 if(y>mid) b1=query(x,y,mid+1,r,k<<1|1)%p;//右子树的最大值 return max(a1,b1);//选一个最大的 } int main() { cin>>m>>p; for(ll i=1;i<=m;i++) { char a; ll b; cin>>a>>b; if(a=='A') { n++; build(n,(b+t)%p,1,m,1);//n为当前是第几个节点 注意叠加t } if(a=='Q') { t=query(n-b+1,n,1,m,1);//注意区间是[n-b+1,n] 因为是倒数的b个数 cout<<t<<endl; } } }