2 条题解

  • 0
    @ 2026-4-21 19:56:09

    思路

    虽然说这是道ST表的题,但是可以用单调栈做。
    每一次询问都是要求后LL个数中最大的,显然如果直接枚举后LL个会TLE,如果可以让后ll个自动排好序就好了……
    这时你看向了单调栈(我好唐啊)
    考虑维护一个单调递减的队列,这样可以保证区间内最大不会被埋没。每一次A操作都在栈后面加入一个新的数,具体大小见题面(如果不懂单调栈的看这里)。至于每一次Q查询就更简单了,只需要在目标区间内lowerboundlower_-bound一下就可以了(别忘记录了)。

    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:锣鼓原题在这里
    这份代码直接交到锣鼓上是不行的,因为在x+tx+t的部分会炸intint需要开longlonglong long。 具体代码:

    #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
      @ 2025-10-8 17:02:08

      A12 ST表 RMQ问题

      #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

      A12*【ST表RMQ问题】[JSOI2008] 最大数

      信息

      ID
      2665
      时间
      1000ms
      内存
      128MiB
      难度
      8
      标签
      递交数
      351
      已通过
      62
      上传者