Luogu2174 小Z的神奇数列
题目描述
小Z最近在研究数列,他需要知道在他所研究的数列中,最大的数是多少(Max),最小的数是多少(Min),最大的数的最小的数次幂是多少(Max^Min),所有数的乘积是多少。要知道,这样的问题是肯定难不倒小Z的。但是,最近小Z突发奇想,想要研究下这个数列的更深层的性质,所以他决定不断的从这个数列中删去一些数,每次删除后都研究下当前数列。由于数列项数很大,这给小Z带来了很大的麻烦,于是小Z请你帮他写一个程序,来完成下列操作。
D x:表示从数列中删除x,保证数列中一定会有x。
B:输出当前数列中的最大数,保证数列不为空。
S:输出当前数列中的最小数,保证数列不为空。
M:输出Max^Min除以317847191的余数,其中Max为当前数列中的最大数,Min为当前数列中的最小数,保证数列不为空。
- T:输出数列中所有数的乘积除以317847191的余数,保证数列不为空。
输入输出格式
输入格式:
第1行:两个正整数N,M,N表示初始数列的长度,M表示操作数。
第2行:N个正整数,第i个数表示初始数列中的第i项Ai,数列中有可能会有相同的数(如遇到删除操作,则只需要删去其中任意一个)。
第3~M+2行:每行表示一个操作,具体格式参见题目描述。
输出格式:
每行一个数,分别表示每个操作的结果(D x操作不需要有输出)。
输入输出样例
输入样例#1:
3 6 2 6 9 M D 9 B S M T输出样例#1:
81 6 2 36 12说明
【数据规模】
49%的数据满足 N<=1000, M<=100, Ai<=4000
100%的数据满足N<=1000000, M<=1000000, Ai<=100000000
由于只有删除操作,并且支持离线,可以读完之后从后往前当作插入来进行。
这样的话取最大,取最小,取乘积,取幂就很容易了。
// update : lower_bound的时候改值的那一行代码是不对的。。。那就不是单调序列了。。。所以需要用multiset来搞的样子。。。(懒得写了)
// 离线算法 快速幂 倍增 #include <iostream> #include <algorithm> #include <cstdio> #include <cstring> #include <cstdlib> #include <set> using namespace std; typedef long long ll; const int N = 1000010; const ll M = 317847191LL; ll pow(ll a, ll b) { ll ret = 1; a %= M; while(b) { if(b & 1) { ret = (ret * a) % M; } b >>= 1; a = (a * a) % M; } return ret; } int n, m; ll mx = 0xcfcfcfcfcfcfcfcfLL, mn = 0x3f3f3f3f3f3f3f3fLL, val[N], seq[N], ans[N], mul; char op[N][5]; int main() { scanf("%d%d", &n, &m); for(int i = 1 ; i <= n ; ++ i) { scanf("%lld", &seq[i]); } sort(seq + 1, seq + 1 + n); for(int i = 1 ; i <= m ; ++ i) { scanf("%s", op[i]); if(*op[i] == 'D') { scanf("%lld", &val[i]); *(lower_bound(seq + 1, seq + 1 + n, val[i])) = 0x3f3f3f3f3f3f3f3fLL; } } mul = 1; for(int i = 1 ; i <= n ; ++ i) { if(seq[i] != 0x3f3f3f3f3f3f3f3fLL) { mx = max(mx, seq[i]); mn = min(mn, seq[i]); mul = (mul * ((ll)seq[i] % M)) % M; } } for(int i = m ; i >= 1 ; -- i) { if(*op[i] == 'D') { mx = max(mx, val[i]); mn = min(mn, val[i]); mul = (mul * ((ll)val[i] % M)) % M; } else if(*op[i] == 'B') { ans[i] = mx; } else if(*op[i] == 'S') { ans[i] = mn; } else if(*op[i] == 'M') { ans[i] = pow(mx, mn); } else if(*op[i] == 'T') { ans[i] = mul; } } for(int i = 1 ; i <= m ; ++ i) { if(*op[i] != 'D') { printf("%lld\n", ans[i]); } } }