題目
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);
}