GalaxyOJ-945 (逆向思维+去重优化)

来源:互联网 发布:vb取整函数 编辑:程序博客网 时间:2024/06/06 01:18

题目

Problem 945: 数列的秘密
Time Limit: 1000 ms Memory Limit: 262144 KB

Problem 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
T

Sample Output

81
6
2
36
12

分析

  • 第一想到线段树,不过发现空间会炸……
  • 后来发现都是对于整个数组的操作,可以想想一次扫过,由于模数不是质数,可以想到倒着做。
  • 再去个重才不超时……

程序

#include <cstdio>#include <algorithm>#define N 1000005#define Ha 317847191#define X q[i].xtypedef 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);}
原创粉丝点击