【线段树模板】【求区间最大值】P1198 [JSOI2008]最大数
题目描述
现在请求你维护一个数列,要求提供以下两种操作:
1、 查询操作。
语法:Q L
功能:查询当前数列中末尾L个数中的最大的数,并输出这个数的值。
限制:LL不超过当前数列的长度。(L > 0)(L>0)
2、 插入操作。
语法:A n
功能:将nn加上tt,其中tt是最近一次查询操作的答案(如果还未执行过查询操作,则t=0t=0),并将所得结果对一个固定的常数DD取模,将所得答案插入到数列的末尾。
限制:nn是整数(可能为负数)并且在长整范围内。
注意:初始时数列是空的,没有一个数。
输入输出格式
输入格式:
第一行两个整数,MM和DD,其中MM表示操作的个数(M \le 200,000)(M≤200,000),DD如上文中所述,满足(0<D<2,000,000,000)(0<D<2,000,000,000)
接下来的MM行,每行一个字符串,描述一个具体的操作。语法如上文所述。
输出格式:
对于每一个查询操作,你应该按照顺序依次输出结果,每个结果占一行。
题目要求过于直球
#include <bits/stdc++.h> #define ll long long using namespace std; const int maxn=2e5+5; int n; ll a[maxn],d; struct node { int l,r; ll id; }t[maxn*4]; void build(int p,int l,int r) { t[p].l=l,t[p].r=r; if(l==r) { t[p].id=a[l]; return; } int mid=(l+r)>>1; build(p*2,l,mid); build(p*2+1,mid+1,r); t[p].id=max(t[p*2].id,t[p*2+1].id); } void change(int p,int x,ll v,int l,int r) { if(l==r) { t[p].id=v; return; } int mid=(l+r)>>1; if(x<=mid) change(p*2,x,v,l,mid); else change(p*2+1,x,v,mid+1,r); t[p].id=max(t[p*2].id,t[p*2+1].id); } ll ask(int l0,int r0,int p,int l,int r) { if(l<=l0&&r>=r0) { return t[p].id; } int mid=(l0+r0)>>1; ll val=-(1<<30); if(mid>=l) val=max(val,ask(l0,mid,p*2,l,r)); if(mid<r) val=max(val,ask(mid+1,r0,p*2+1,l,r)); return val; } int main() { scanf("%d %lld",&n,&d); int len=0; ll t=0; for(int i=1;i<=n;i++) { char ch; ll x; scanf(" %c %lld",&ch,&x); //cout<<ch<<" "<<x<<endl; if(ch=='A') { change(1,++len,(x+t)%d,1,n); } else { if(x==0) t=0; else t=ask(1,n,1,len-x+1,len); printf("%lld\n",t); } } return 0; }