Codeforces Round #688 (Div. 2) C
阿新 • • 發佈:2020-12-06
Codeforces Round #688 (Div. 2) C
大意
略...
思維
艹,比賽時假了一個 \(\Theta(n^4)\) 做法,以為是 \(\Theta(n^2)\) ,調到天荒地老。
有 \(n^2\) 個點,我們需要 \(\Theta(n^2)\) 做法。
假設當前列舉到的點 \(a\) 的值是 \(d\) ,若 \(d\) 的最優結果下我們選擇了在 \(d\) 上方的一個點,此時討論一下:
若該點與 \(a\) 在同一列,那麼由三角形面積公式可以得知貪心選擇與 \(a\) 在同一行且離 \(a\) 最遠的點修改一定是最優。
若不在同一列,我們只能在與 \(a\) 同一行的點上選擇,此時依舊選擇最遠的點。
綜上,當我們考慮選擇 \(a\) 上方的點時,最優結果與該點是否與 \(a\) 在同一列無關,因為選擇與 \(a\) 在同一行上的某點一定能達成最優解。
容易發現,我們只想知道 \(a\) 的上方離 \(a\) 所在的行最遠的且值為 \(d\) 的點。
可以很容易的將選擇上方拓展到選擇所有四個方向。
程式碼
#include <iostream> #include <cstdio> #include <algorithm> #include <cmath> #include <cstring> using namespace std; #define ll long long #define ull unsigned long long #define cint const int& #define Pi acos(-1) const int mod = 998244353; const int inf_int = 0x7fffffff; const ll inf_ll = 0x7fffffffffffffff; const double ept = 1e-9; int t, n; int a[2020][2020]; int loc[5][10]; int ans[10]; // 1,3 row 2,4 column int main() { char tmp; cin >> t; while(t--) { cin >> n; for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) { cin >> tmp; a[i][j] = tmp-'0'; } memset(loc, -1, sizeof loc); memset(ans, 0, sizeof ans); for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) for(int k=1; k<=4; k++) { int r = a[i][j]; if(loc[k][r]<0) { if(k&1) loc[k][r] = i; else loc[k][r] = j; } else { if(k==2) loc[k][r] = min(loc[k][r],j); if(k==3) loc[k][r] = max(loc[k][r],i); if(k==4) loc[k][r] = max(loc[k][r],j); } } for(int i=1; i<=n; i++) for(int j=1; j<=n; j++) { int r = a[i][j]; ans[r] = max(ans[r], max(j-1,n-j)*max(i-loc[1][r],loc[3][r]-i)); ans[r] = max(ans[r], max(i-1,n-i)*max(j-loc[2][r],loc[4][r]-j)); } for(int i=0; i<=9; i++) cout << ans[i] << ' '; cout << endl; } return 0; }
補題一時爽,當場做題火葬場...