CF problem: (D) Maximum Product Strikes Back
阿新 • • 發佈:2022-04-04
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; }