题目链接:Codeforces Round #550 (Div. 3) – D
题意:给你一个数组,对于每一个数都可以有两种操作类型,问你通过最少几次操作之后数组里的元素都相同,题目保证这个数存在。
思路:题目说保证这个数存在,并且要求操作数最少,那么我们假设最后所有数都为x
- 一个数经过操作一肯定会变大,经过操作二肯定会变小
- 每个数经过最多一次操作之后一定可以变成x
- 那么对于n个数,假如x从没有出现过,那么所有数都需要进行操作,一共n次,那我们为什么不找已经出现过的呢,肯定小于n次,所以最后的x肯定是数组中出现次数最多的那个数,假设为y
- 对于每一个数,只要小于y一定要进行操作一,大于y一定要进行操作二
- 那么在y之前的数肯定要选他右边位置的数,在y之后的数肯定要选他左边的数
- 因为我们可以先把离y进的先变成y在往两边延伸。同时对于与y相邻的数来说:
如果是在y左边:
那么当y > ai时,需要进行操作一使ai变大 ai = ai+(ai-aj)那么我们选可以选aj为y,那么公式就变成了ai = ai+y-ai = y
其他情况同理
样例:
#include<bits/stdc++.h>
using namespace std;
int main()
{
int n,mx = -1,p,flag;
int a[200010],b[200010];
memset(b,0,sizeof(b));
cin >> n;
for(int i = 1; i <= n; i++)
{
cin >> a[i];
b[a[i]]++;
if(b[a[i]] > mx)
{
mx = b[a[i]];
flag = a[i];
p = i;
}
}
int tot = 0;
for(int i = 1; i <= n; i++)
{
if(a[i] != flag) tot++;
}
cout << tot << endl;
for(int i = p; i >= 1; i--)
{
if(a[i] == flag) continue;
else if(a[i] > flag) printf("2 %d %d\n",i,i+1);
else printf("1 %d %d\n",i,i+1);
}
for(int i = p; i <= n; i++)
{
if(a[i] == flag) continue;
else if(a[i] > flag) printf("2 %d %d\n",i,i-1);
else printf("1 %d %d\n",i,i-1);
}
return 0;
}