1. 程式人生 > 其它 >CF problem: (D) Maximum Product Strikes Back

CF problem: (D) Maximum Product Strikes Back

Problem - D - Codeforces

 

 

 

Example input
5
4
1 2 -1 2
3
1 1 -2
5
2 0 -2 2 -1
3
-2 -1 -1
3
-1 -2 -2

 

output
0 2
3 0
2 0
0 1
1 0

 

 

最近賽中敲不出程式碼, 賽後倒是鎮靜了, 我也醉了

簡述下思路及變數意義: 

這裡採取從前到尾遍歷,由於資料範圍不能完全連乘2e5個的2, 所以我們採取計數方法,

num表示絕對值為2的個數, sign表示當前是正負數, min是從上一個0到現在連乘絕對值最小的負數

帶有res的4個變數是截止到1~i的最優方案: res是乘積最大的2的個數, resl是連乘的左邊界, resr是連乘的右邊界, res0是前面最近所在0的下標+1

解釋不清了, 看程式碼吧

 

#include <bits/stdc++.h>

using namespace std;
typedef long long LL;
const int N = 2e5+10;

LL a[N];
int main()
{
    int t;
    scanf("%d", &t);
    while(t --)
    {
        int n;
        scanf("%d", &n);
        
        LL sign = 1, num = 0;
        LL res = 0, minn = -99
, resmin = 1, res0 = 1; LL resl=n+1, resr = n; for(int i = 1; i <= n; i ++) { scanf("%lld", &a[i]); //以下四行相當於*a[i], sign表示正負, num表示絕對值=2的個數 if(a[i] == -2) num ++, sign = -1*sign; else if(a[i]==2) num++;
else if(a[i]==-1) sign = -1*sign; else if(a[i]==0) num=0;
//從頭到尾相乘: (數字為0, 下標為res0 - 1) ~ i
if(sign>0 && num*sign > res) { res = num*sign; //res 正負表示正負, 大小表示多少個2相乘 resl = res0; //resl:結果左邊界 resr = i;//resr:結果右邊界 } //中間一段相乘: 即 if(sign<0 && minn!=-99 && minn-num*sign > res) { res = minn-num*sign; resl = resmin; resr = i; }
      //以下是後面特例的初始化
if(a[i]==0) { res0 = i+1;//前面最近所在0的下標+1 sign=1; minn = -99;//絕對值最小的負數的大小 resmin = i+1;//絕對值最小的負數的下標後一位 } if(sign<0 && num*sign > minn) minn = num*sign, resmin = i+1; } cout << resl-1 << ' '<< n-resr<<'\n'; } return 0; }