题目
Problem 945: 数列的秘密
Time Limit: 1000 ms Memory Limit: 262144 KBProblem Description
WSW最近在研究数列,他需要知道在他所研究的数列中,最大的数是多少(Max),最小的数是多少(Min),最大的数的最小的数次幂是多少(Max^Min),所有数的乘积是多少。
要知道,这样的问题是肯定难不倒WSW的。但是,最近WSW突发奇想,想要研究下这个数列的更深层的性质,所以他决定不断的从这个数列中删去一些数,每次删除后都研究下当前数列。由于数列项数很大,这给WSW带来了很大的麻烦,于是WSW请你帮他写一个程序,来完成下列操作。
1. D x:表示从数列中删除x,保证原数列中一定会有x。(注意这里是如果数列中有多个x,那么就要先把x全部删掉,如果某个x在D的时候以前已经被D过了,请自动忽略这一次的D)
2. B:输出当前数列中的最大数,保证数列不为空。
3. S:输出当前数列中的最小数,保证数列不为空。
4. M:输出Max^Min 除以317847191 的余数,其中Max 为当前数列中的最大数,Min 为当前数列中的最小数,保证数列不为空。
5. T:输出数列中所有数的乘积除以317847191 的余数,保证数列不为空。Input
共M+2 行
第1 行:两个正整数N,M,N 表示初始数列的长度,M 表示操作数。
第2 行:N 个正整数,第i 个数表示初始数列中的第i 项Ai,数列中有可能会有相同的数。
第3~M+2 行:每行表示一个操作,具体格式参见题目描述。对于所有数据N<=1,000,000, M<=1,000,000, Ai<=100,000,000
Output
每行一个数,分别表示每个操作的结果(D x 操作不需要有输出)。
Sample Input
3 6
2 6 9
M
D 9
B
S
M
TSample Output
81
6
2
36
12
分析
- 第一想到线段树,不过发现空间会炸……
- 后来发现都是对于整个数组的操作,可以想想一次扫过,由于模数不是质数,可以想到倒着做。
- 再去个重才不超时……
程序
#include <cstdio>
#include <algorithm>
#define N 1000005
#define Ha 317847191
#define X q[i].x
typedef long long ll;
using namespace std;
struct que{char Q;ll x,y;} q[N];
ll i,n,m,k,a[N],S[N],F[N],num,Ans=1,Min=2147483647,Max=-2147483647;
char s[10];
ll ksm(ll xx,ll yy){
long long x=xx,y=yy,ret=1;
for (; y; y>>=1,x=(x*x)%Ha)
if (y&1) ret=(ret*x)%Ha;
return (ll)ret;
}
int main(){
scanf("%lld%lld",&n,&m);
for (i=1; i<=n; i++) scanf("%lld",&a[i]);
sort(a+1,a+n+1);
for (i=1; i<=n; i++) if (a[i]!=a[i-1]) S[++num]++; else S[num]++;
unique(a+1,a+n+1);
for (i=1; i<=m; i++){
q[i].Q=(scanf("%s",s),s[0]);
if (s[0]=='D'){
scanf("%lld",&X);
k=lower_bound(a+1,a+num+1,X)-a;
if (!F[k]) F[k]=i;
}
}
for (i=1; i<=num; i++) if (!F[i]) Ans=(Ans*ksm(a[i],S[i]))%Ha,Min=min(Min,a[i]),Max=max(Max,a[i]);
for (i=m; i; i--){
if (q[i].Q=='D'){ //添加 x
k=lower_bound(a+1,a+num+1,X)-a;
if (F[k]!=i) continue;
Ans=(Ans*ksm(q[i].x,S[k]))%Ha;
Min=min(Min,X);
Max=max(Max,X);
}
if (q[i].Q=='B'){ //输出最大值
q[i].y=Max;
}
if (q[i].Q=='S'){ //输出最小值
q[i].y=Min;
}
if (q[i].Q=='M'){ //Max^Min
k=ksm(Max,Min);
q[i].y=k;
}
if (q[i].Q=='T'){ //输出乘积
q[i].y=Ans;
}
}
for (ll i=1; i<=m; i++) if (q[i].Q!='D') printf("%lld\n",q[i].y);
}