2 条题解
-
0
思路
虽然说这是道ST表的题,但是可以用单调栈做。
每一次询问都是要求后个数中最大的,显然如果直接枚举后个会TLE,如果可以让后个自动排好序就好了……
这时你看向了单调栈(我好唐啊)
考虑维护一个单调递减的队列,这样可以保证区间内最大不会被埋没。每一次A操作都在栈后面加入一个新的数,具体大小见题面(如果不懂单调栈的看这里)。至于每一次Q查询就更简单了,只需要在目标区间内一下就可以了(别忘记录了)。AC代码
#include<bits/stdc++.h> using namespace std; const int N=2e5+10; int a[N],q[N]; char s[3]; int main() { int T,p;scanf("%d%d",&T,&p); int siz=0,len=0,t=0; while(T--) { int x; scanf("%s%d",s,&x); if(s[0]=='A') { a[++siz]=(x+t)%p; while(len&&a[q[len]]<a[siz])len--; q[++len]=siz; } else { int id=lower_bound(q+1,q+len+1,siz-x+1)-q; t=a[q[id]]; printf("%d\n",a[q[id]]); } } return 0; }PS:锣鼓原题在这里
这份代码直接交到锣鼓上是不行的,因为在的部分会炸需要开。 具体代码:#include<bits/stdc++.h> #define int long long using namespace std; const int N=2e5+10; int a[N],q[N]; char s[3]; signed main() { int T,p;scanf("%lld%lld",&T,&p); int siz=0,len=0,t=0; while(T--) { int x; scanf("%s%lld",s,&x); if(s[0]=='A') { a[++siz]=((x+t)%p+p)%p; while(len&&a[q[len]]<a[siz])len--; q[++len]=siz; } else { int id=lower_bound(q+1,q+len+1,siz-x+1)-q; t=a[q[id]]; printf("%lld\n",a[q[id]]); } } return 0; } -
0
#include <bits/stdc++.h> using namespace std; const int N=2e5+5; int f[N][20],lg[N];//f[x][i]表示 a[x - 2^i +1] ~~~ a[x] 的最大值 template<typename T>void qr(T& x) { x=0;int f=1;char c=getchar(); for( ;!isdigit(c);c=getchar())if(c=='-')f=-1; for( ; isdigit(c);c=getchar())x=(x<<1)+(x<<3)+(c&15); x=x*f; } int main() { int n=0,m,p;qr(m);qr(p); lg[1]=0;for(int i=2;i<=m;i++)lg[i]=lg[i>>1]+1; char s[5];int x,last=0,l,r,k; while(m--) { scanf("%s",s);qr(x); if(s[0]=='A') { x=(last+x)%p; f[++n][0]=x;for(int i=1; (1<<i)<=n;i++)f[n][i]=max(f[n][i-1],f[n-(1<<(i-1))][i-1]); } else { l=n-x+1,r=n,k=lg[r-l]; last=max(f[l+(1<<k)-1][k],f[r][k]); //两者有重叠部分,但是不影响求最大值 printf("%lld\n",last); } } return 0; }
- 1
信息
- ID
- 2665
- 时间
- 1000ms
- 内存
- 128MiB
- 难度
- 8
- 标签
- 递交数
- 351
- 已通过
- 62
- 上传者