BZOJ1012:[JSOI2008]最大数——题解
https://www.lydsy.com/JudgeOnline/problem.php?id=1012
https://www.luogu.org/problemnew/show/P1198
现在请求你维护一个数列,要求提供以下两种操作:1、 查询操作。语法:Q L 功能:查询当前数列中末尾L
个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。2、 插入操作。语法:A n 功能:将n加
上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取
模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个
数。
倒着来st表即可。
(当然平衡树啊动态线段树啊分块啊都能做,选一个最简单的做。)
洛谷数据很恶心,如果你TLE了不妨与main函数对比一下。
#include<cstdio> #include<cctype> #include<cstring> #include<cmath> #include<algorithm> #include<iostream> using namespace std; typedef long long ll; const int N=4e5+5; const int B=18; inline int read(){ int X=0,w=0;char ch=0; while(!isdigit(ch)){w|=ch=='-';ch=getchar();} while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar(); return w?-X:X; } ll dp[N][B+4]; int lg[N]; char s[101]; inline ll qry(int l,int r){ if(l>r)return 0; int h=lg[r-l+1]; return max(dp[r][h],dp[l+(1<<h)-1][h]); } int main(){ int m=read(),d=read(),n=0;ll t=0,k; lg[1]=0; while(m--){ scanf("%s%lld",s,&k); if(s[0]=='Q'){ printf("%lld",t=qry(n-k+1,n)); putchar(10); } if(s[0]=='A'){ k=(k+t)%d; dp[++n][0]=k; if(n!=1){ lg[n]=lg[n-1]; if((1<<lg[n]+1)==n)lg[n]++; } for(int j=1;j<=lg[n];j++){ if(n-(1<<j)+1<1)break; dp[n][j]=max(dp[n][j-1],dp[n-(1<<j-1)][j-1]); } } } return 0; }
+++++++++++++++++++++++++++++++++++++++++++
+本文作者:luyouqi233。 +
+欢迎访问我的博客:http://www.cnblogs.com/luyouqi233/ +
+++++++++++++++++++++++++++++++++++++++++++