Submission #1035982

#TimeUsernameProblemLanguageResultExecution timeMemory
1035982RequiemSailing Race (CEOI12_race)C++17
80 / 100
3074 ms19036 KiB
#include<bits/stdc++.h> //#define int long long #define pb push_back #define fast ios_base::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr); #define MOD 1000000007 #define inf 1e18 #define fi first #define se second #define FOR(i,a,b) for(int i=a;i<=b;i++) #define FORD(i,a,b) for(int i=a;i>=b;i--) #define sz(a) ((int)(a).size()) #define endl '\n' #define pi 3.14159265359 #define TASKNAME "sailrace" template<typename T> bool maximize(T &res, const T &val) { if (res < val){ res = val; return true; }; return false; } template<typename T> bool minimize(T &res, const T &val) { if (res > val){ res = val; return true; }; return false; } using namespace std; typedef pair<int,int> ii; typedef pair<int,ii> iii; typedef vector<int> vi; const int MAXN = 3e5 + 9; string str; int n, k; vector<int> g[MAXN], backEdge[MAXN]; void extract(int curId){ int num = 0, cnt = 0; // cout << str << endl; str = str + ' '; for(int i = 0; i < str.length(); i++){ if (str[i] != ' ') { num = num * 10 + (str[i] - '0'); // cout << num << ' ' << str[i] - '0' << endl; } else { if (num != 0) { g[curId].pb(num); backEdge[num].pb(curId); cnt++; // cout << curId << ' ' << num << endl; } else break; num = 0; } } assert(cnt <= 500); } namespace subtask1{ bool check(){ return k == 0; } int dp[2][501][501], memo[2][501][501], backward = 0; int bestI = 0, res = 0; int goBack(int id){ return (id - backward <= 0) ? id - backward + n : (id - backward); } int goUp(int id){ return (id + backward) - ((id + backward > n) ? (n) : 0); } int memorization(int state, int Larc, int Rarc){ if (dp[state][Larc][Rarc] != -1) return dp[state][Larc][Rarc]; if (memo[state][goUp(Larc)][goUp(Rarc)] != -1) return memo[state][goUp(Larc)][goUp(Rarc)]; if (Larc >= Rarc) return 0; dp[state][Larc][Rarc] = 0; int cur = goUp((state) ? Rarc : Larc); if (state == 0){ for(auto v: g[cur]){ int curV = goBack(v); // cout << cur << ' ' << curV << ' ' << v << endl; // cout << cur << ' ' << v << endl; if (curV > Larc and curV <= Rarc) { maximize(dp[0][Larc][Rarc], 1 + max(memorization(0, curV, Rarc), memorization(1, Larc + 1, curV))); } } } else{ for(auto v: g[cur]){ int curV = goBack(v); if (curV >= Larc and curV < Rarc) { maximize(dp[1][Larc][Rarc], 1 + max(memorization(0, curV, Rarc - 1), memorization(1, Larc, curV))); } } } memo[state][goUp(Larc)][goUp(Rarc)] = dp[state][Larc][Rarc]; // cout << "MEMO: " << state << ' ' << goUp(Larc) << ' ' << goUp(Rarc) << ' ' << memo[state][goUp(Larc)][goUp(Rarc)] << endl; // cout << "DP: " << state << ' ' << Larc << ' ' << Rarc << ' ' << dp[state][Larc][Rarc] << endl; return dp[state][Larc][Rarc]; } int modify(int x){ return (x > n) ? (x - n) : x; } bool onRange(int l, int r, int x){ return x >= l and x <= r; } bool onArc(int l, int r, int x){ l = modify(l); r = modify(r); if (l > r) r += n; return onRange(l, r, x) | onRange(l, r, x + n); } int dist(int i, int j){ i = modify(i); j = modify(j); return min(abs(i - j), abs(i + n - j)); } bool RightArc(int l, int r, int x){ if (l > r) { r += n; } return dist(r, x) < dist(l, x); } void solve(int print = 1){ memset(memo, -1, sizeof(memo)); for(int i = 1;i <= n; i++){ memset(dp, -1, sizeof(dp)); backward = i - 1; // cout << i << endl; int mx = memorization(0, 1, n); if (maximize(res, mx)){ bestI = i; } // cout << endl; } if (print == 1) cout << res << endl; if (print == 1) cout << bestI << endl; for(int i = 1; i <= n; i++){ for(int j = 1; j <= n; j++){ for(int state = 0; state < 2; state++){ if (memo[state][i][j] == -1) memo[state][i][j] = 0; } } } for(int i = 1; i <= n; i++){ for(auto v: g[i]){ maximize(memo[0][i][v], 1); maximize(memo[1][v][i], 1); } } for(int len = 1; len <= n; len++){ for(int i = 1, j = i + len - 1; i <= n; i++){ if (j > n) j -= n; for(int state = 0; state < 2; state++){ int cur = (state == 0) ? i : j; for(auto v: backEdge[cur]){ if (!onArc(i, j, v)) { if (RightArc(i, j, v)) maximize(memo[1][i][v], memo[state][i][j] + 1); else maximize(memo[0][v][j], memo[state][i][j] + 1); // if (i == 3 and j == 5) cout << cur << ' ' << v << ' ' << memo[0][2][5] << endl; } } } } } for(int i = 1; i <= n; i++){ for(int j = 1; j <= n; j++){ for(int state = 0; state < 2; state++){ // cout << state << ' ' << i << ' ' << j << ' ' << memo[state][i][j] << endl; } } } } } namespace subtask2{ bool check(){ return k == 1; } int backward = 0; int goVirtual(int id){ return (id - backward <= 0) ? id - backward + n : (id - backward); } int goOrigin(int id){ return (id + backward) - ((id + backward > n) ? (n) : 0); } int dpRight[505], dpLeft[505]; int solveRight(int cur, int intersect){ if (dpRight[cur] != -1) return dpRight[cur]; int u = goOrigin(cur); dpRight[cur] = 0; for(auto v: g[u]){ int curV = goVirtual(v); if (curV < cur and curV > 1){ maximize(dpRight[cur], solveRight(curV, intersect) + 1); } else if (curV > intersect and cur != intersect) { maximize(dpRight[cur], subtask1::memo[1][goOrigin(intersect + 1)][goOrigin(curV)] + 1); maximize(dpRight[cur], subtask1::memo[0][goOrigin(curV)][goOrigin(n)] + 1); } } // cout << "CUR: " << u << ' ' << cur << ' ' << dpRight[cur] << endl; return dpRight[cur]; } int solveLeft(int cur, int intersect){ if (dpLeft[cur] != -1) return dpLeft[cur]; int u = goOrigin(cur); dpLeft[cur] = 0; for(auto v: g[u]){ int curV = goVirtual(v); if (curV > cur){ maximize(dpLeft[cur], solveLeft(curV, intersect) + 1); } else if (curV > 1 and curV < intersect and cur != intersect) { maximize(dpLeft[cur], subtask1::memo[0][goOrigin(curV)][goOrigin(intersect - 1)] + 1); maximize(dpLeft[cur], subtask1::memo[1][goOrigin(2)][goOrigin(curV)] + 1); } } // cout << "LEFTCUR: " << intersect << ' ' << u << ' ' << cur << ' ' << dpLeft[cur] << endl; return dpLeft[cur]; } void solve(){ subtask1::solve(0); int res = subtask1::res, bestI = subtask1::bestI; for(int i = 1; i <= n; i++){ backward = i - 1; for(auto v: g[i]){ for(int j = 1; j <= goVirtual(v); j++){ dpRight[j] = -1; } for(int j = goVirtual(v); j <= n; j++){ dpLeft[j] = -1; } // cout << 1 << ' ' << goVirtual(v) << endl; int m1 = 0, m2 = 0; m1 = solveRight(goVirtual(v), goVirtual(v)) + 1; m2 = solveLeft(goVirtual(v), goVirtual(v)) + 1; if (maximize(res, m1) or maximize(res, m2)){ bestI = i; } } } cout << res << endl; cout << bestI << endl; } } main() { fast; if (fopen(TASKNAME".inp","r")){ freopen(TASKNAME".inp","r",stdin); freopen(TASKNAME".out","w",stdout); } cin >> n >> k; cin.ignore(); for(int i = 1; i <= n; i++){ getline(cin, str); extract(i); } if (subtask1::check()) return subtask1::solve(), 0; if (subtask2::check()) return subtask2::solve(), 0; } /** Warning: - MLE / TLE? - Gioi han mang? - Gia tri max phai luon gan cho -INF - long long co can thiet khong? - tran mang. - code can than hon - Nho sinh test de tranh RTE / TLE --> Coi lai truoc khi nop **/

Compilation message (stderr)

race.cpp: In function 'void extract(int)':
race.cpp:30:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::__cxx11::basic_string<char>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   30 |      for(int i = 0; i < str.length(); i++){
      |                     ~~^~~~~~~~~~~~~~
race.cpp: At global scope:
race.cpp:269:1: warning: ISO C++ forbids declaration of 'main' with no type [-Wreturn-type]
  269 | main()
      | ^~~~
race.cpp: In function 'int main()':
race.cpp:273:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  273 |         freopen(TASKNAME".inp","r",stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
race.cpp:274:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  274 |         freopen(TASKNAME".out","w",stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...