这个题有毒,卡最大值。。。我开1 << 30爆零让我以为我分块错了。。。gg,然后去写RMQ,但是这个题st表是真简单啊。后来刘胜与巨佬一眼看出来我最大值不够大。。。然后1LL<<60也爆零,然而1 << 60 AC,(60LL)AC,1e8爆零。。。无良数据。。。
题目:
Description 现在请求你维护一个数列,要求提供以下两种操作:1、 查询操作。语法:Q L 功能:查询当前数列中末尾L 个数中的最大的数,并输出这个数的值。限制:L不超过当前数列的长度。2、 插入操作。语法:A n 功能:将n加 上t,其中t是最近一次查询操作的答案(如果还未执行过查询操作,则t=0),并将所得结果对一个固定的常数D取 模,将所得答案插入到数列的末尾。限制:n是非负整数并且在长整范围内。注意:初始时数列是空的,没有一个 数。 Input 第一行两个整数,M和D,其中M表示操作的个数(M <= 200,000),D如上文中所述,满足D在longint内。接下来 M行,查询操作或者插入操作。 Output 对于每一个询问操作,输出一行。该行只有一个数,即序列中最后L个数的最大数。 Sample Input 5 100 A 96 Q 1 A 97 Q 1 Q 2 Sample Output 96 93 96
分块代码:
#include<iostream> #include<cstdio> #include<cmath> #include<ctime> #include<queue> #include<algorithm> #include<cstring> using namespace std; #define duke(i,a,n) for(int i = a;i <= n;i++) #define lv(i,a,n) for(int i = a;i >= n;i--) #define clean(a) memset(a,0,sizeof(a)) const long long INF = (60LL); typedef long long ll; typedef double db; template <class T> void read(T &x) { char c; bool op = 0; while(c = getchar(), c < '0' || c > '9') if(c == '-') op = 1; x = c - '0'; while(c = getchar(), c >= '0' && c <= '9') x = x * 10 + c - '0'; if(op) x = -x; } template <class T> void write(T x) { if(x < 0) putchar('-'), x = -x; if(x >= 10) write(x / 10); putchar('0' + x % 10); } int bl,n,m,d,len = 0; ll k[200005]; ll a[200005]; char s[5]; int main() { read(m);read(d); bl = sqrt(m); int t = 0,l = 1; duke(i,1,m) { ll x; scanf("%s%lld",s,&x); if(s[0] == 'Q') { n = len - x + 1; if(n > (len / bl - 1) * bl) { ll maxn = 0; duke(i,n,len) { if(maxn < a[i]) maxn = a[i]; } printf("%lld ",maxn); t = maxn; } else { ll maxn = 0; duke(i,n / bl + 2,len / bl) { if(maxn < k[i]) maxn = k[i]; } duke(i,l,len) { if(maxn < a[i]) maxn = a[i]; } duke(i,n,(n / bl + 1) * bl) { if(maxn < a[i]) maxn = a[i]; } t = maxn; printf("%lld ",maxn); } } else { x += t; if(x < 0) x += d; x %= d; a[++len] = x; if(len % bl == 0) { ll maxn = INF; duke(i,l,len) { if(maxn < a[i]) maxn = a[i]; } k[len / bl] = maxn; l = len + 1; } } } } /* 9 100 A 1 A 2 A 3 A 4 A 5 Q 3 A 7 A 8 Q 4 */ /* 5 100 A 96 Q 1 A 97 Q 1 Q 2 */
RMQ代码:
#include <cstdio> #include <cmath> #include <iostream> #include <cstring> #define ll long long using namespace std; ll a[200001],f[200001][21],t,D; int n,m; bool flag; void change(int u) //用change函数来进行修改 { f[u][0]=a[u]; for(int i=1; u-(1<<i)>=0; i++) f[u][i]=max(f[u][i-1],f[u-(1<<(i-1))][i-1]); } ll find(int x,int y) { double t=log(y-x+1)/log(2); int K=t; return max(f[y][K],f[x+(1<<K)-1][K]); } int main() { memset(f,0,sizeof(f)); scanf("%d%lld",&m,&D); for (int i=1; i<=m; i++) { char c; cin>>c; ll x; if (c=='A') //根据题面的操作,注意细节。 { scanf("%lld",&x); a[++n]=(x+t)%D; change(n); } else { int L; scanf("%d",&L); ll ans; if (L==1) { printf("%lld ",a[n]); t=a[n]; continue; } ans=find(n-L+1,n); printf("%lld ",ans); t=ans; } } return 0; }