题目链接 :
https://codeforces.com/contest/1855/problem/C1
https://codeforces.com/contest/1855/problem/C2
(c1为简单版)
解题思路 :
C1限制50次 , C2限制 31 次
那么对于这种题,我们先从特殊的情况去考虑
1.全是正数时
联想到前缀和可以想到,a2 + a1 > a1 ....
那么操作次数为19次
2.全是负数时
可以使用后缀和
操作次数为19次
3.有负有正时(划归思想)
对于C1,我们可以构造一个大于20的正数,然后转换成情况1,
倍增速度很快,最坏情况为
1 , 2 , 4 , 8 , 16 , 32共5次操作
把负数全部变成正数的最坏情况为19次操作
5 + 19 + 19 = 43 显然可以解决C1
对于C2
同样运用前缀思想是有利的
那么剩余的操作次数为31 - 19 = 12
设正数n1个,负数n2个,
正数最大值o1 , 负数最大值 o2
于是我们可以想到
当n1 <= 12 时,是否满足abs(o2) >= o1,使其正好12次操作内变成情况1或者情况2
那么它的对立面就是
当n2 <= 12时,o1 >= abs(o2)
如果对于第二个条件都不满足
那么我们去看另一个条件
n1 <= 7
那么我们构造一个大于20的负数
最坏情况为5次操作
全变负数 7次操作
前缀操作19次
5 + 7 + 19 = 31正好成立
那么它的对立面是
n2 <= 7
此题便已解决了
c1代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
#define pii pair <ll , ll>
const ll N = 2e5 + 10;
const ll mod = 33789051;
const ll INF = 1e9 + 10;
ll a[N];
void slove() {
ll n; cin >> n;
ll op1 = 0 , op2 = 0;
ll zz;
for(ll i = 1 ; i <= n ; i++){
cin >> a[i];
if(a[i] > 0) op1 = a[i],zz = i;
else if(a[i] < 0) op2 = a[i];
}
vector <pii> ans;
if(op1 != 0 && op2 == 0){
for(ll i = 2 ; i <= n ; i++){
ans.push_back({i , i - 1});
}
}
else if(op1 == 0 && op2 != 0){
for(ll i = n - 1 ; i >= 1 ; i--){
ans.push_back({i , i + 1});
}
}
else if(op1 != 0 && op2 != 0){
while(a[zz] < 20){
a[zz] += a[zz];
ans.push_back({zz,zz});
}
for(ll i = 1 ; i <= n ; i++){
ans.push_back({i,zz});
}
for(ll i = 2 ; i <= n ; i++){
ans.push_back({i,i - 1});
}
}
cout << ans.size() << endl;
for(auto x : ans){
cout << x.first << " " << x.second << endl;
}
}
int main()
{
//freopen("classroom.in", "r", stdin);
//freopen("classroom.out", "w", stdout);
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int tt = 1;
cin >> tt;
while (tt--) slove();
return 0;
}
c2代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define endl '\n'
#define pii pair <ll , ll>
const ll N = 2e5 + 10;
const ll mod = 33789051;
const ll INF = 1e9 + 10;
ll a[N];
void slove() {
ll n; cin >> n;
ll n1 = 0 , n2 = 0;
ll o1 = 0 , o2 = 0;
ll z1 = 0 , z2 = 0;
for(ll i = 1 ; i <= n ; i++){
cin >> a[i];
if(a[i] > 0){
if(o1 < a[i]){
o1 = a[i];
z1 = i;
}
n1++;
}
if(a[i] < 0){
if(o2 > a[i]){
o2 = a[i];
z2 = i;
}
n2++;
}
}
vector <pii> ans;
if(n1 > 0 && n2 == 0){
for(ll i = 2 ; i <= n ; i++){
ans.push_back({i , i - 1});
}
}
else if(n1 == 0 && n2 > 0){
for(ll i = n - 1 ; i >= 1 ; i--){
ans.push_back({i , i + 1});
}
}
else if(n1 > 0 && n2 > 0){
if(n1 <= 12 && abs(o2) >= o1){
for(ll i = 1 ; i <= n ; i++){
if(a[i] > 0){
ans.push_back({i,z2});
}
}
for(ll i = n - 1 ; i >= 1 ; i--){
ans.push_back({i,i + 1});
}
}
else if(n2 <= 12 && o1 >= abs(o2)){
for(ll i = 1 ; i <= n; i++){
if(a[i] < 0){
ans.push_back({i , z1});
}
}
for(ll i = 2 ; i <= n ; i++){
ans.push_back({i , i - 1});
}
}
else if(n1 <= 7){
while(a[z2] > -20){
a[z2] += a[z2];
ans.push_back({z2 ,z2});
}
for(ll i = 1 ; i <= n ; i++){
if(a[i] > 0){
ans.push_back({i , z2});
}
}
for(ll i = n - 1 ; i >= 1 ; i--){
ans.push_back({i, i + 1});
}
}
else if(n2 <= 7){
while(a[z1] < 20){
a[z1] += a[z1];
ans.push_back({z1,z1});
}
for(ll i = 1 ; i <= n ; i++){
if(a[i] < 0){
ans.push_back({i , z1});
}
}
for(ll i = 2 ; i <= n ; i++){
ans.push_back({i , i - 1});
}
}
}
cout << ans.size() << endl;
for(auto x : ans){
cout << x.first << " " << x.second << endl;
}
}
int main()
{
//freopen("classroom.in", "r", stdin);
//freopen("classroom.out", "w", stdout);
ios::sync_with_stdio(false);
cin.tie(0); cout.tie(0);
int tt = 1;
cin >> tt;
while (tt--) slove();
return 0;
}