用set代替模拟双端带顺序的队列
用set代替模拟双端带顺序的队列
今天做了一道题,做了好久,因为我太菜了。
题目:
A - Max Mod Min
Problem Statement
You are given a sequence of NN positive integers: A=(A_1,A_2,\dots,A_N)A=(A1,A2,…,A**N).
You will repeat the following operation until the length of AA becomes 11.
- Let kk be the length of AA before this operation. Choose integers ii and jj such that \max({A_1,A_2,\dots,A_{k}})=A_i,\min({A_1,A_2,\dots,A_{k}})=A_jmax({A1,A2,…,A**k})=A**i,min({A1,A2,…,A**k})=A**j, and i \neq ji\=j. Then, replace A_iA**i with (A_i \bmod A_j)(A**imodA**j). If A_iA**i becomes 00 at this moment, delete A_iA**i from AA.
Find the number of operations that you will perform. We can prove that, no matter how you choose i,ji,j in the operations, the total number of operations does not change.
Constraints
- 2 \le N \le 2 \times 10^52≤N≤2×105
- 1 \le A_i \le 10^91≤A**i≤109
- All values in input are integers.
分析
这道题就是说,每次从数列中拿出最大的一个数和最小的一个数,取余,然后如果结果不为0,原来大的那个数,用余数代替,如果为0,直接删除大的数。
这道题我最初的思路是用数组模拟双端队列,先放到数组里面,然后排序,然后进行操作,但是用数组的话,这个队列的对头一直往前走的话,会超出范围,会RE,我RE了好多次。后来想到set是有顺序的,于是直接用set模拟双端队列,s.begin()就是对头,s.end()--就是队尾,然后insert直接插入。
要注意的一点是,set里不会重复,所以插入pair而不是直接插入数字,pair的second用一个递增的数把相同的数区分好就行。
代码:
#include "algorithm"
#include "iostream"
#include "set"
#include "utility"
using namespace std;
const int N = 1000005;
// int a[N];
int n;
set<pair<int,int> >s;
int main() {
int n;
scanf("%d",&n);
int i;
for(i = 0; i<n; i++) {
int t;
scanf("%d",&t);
s.insert({t,i});
}
int res = 0;
while(s.size() >1) {
auto l = s.end();
l--;
int t = (*l).first % (*(s.begin())).first;
res++;
if(t > 0) {
s.insert({t,i});
i++;
}
s.erase(l);
}
printf("%d\n",res);
}