답안 #1035995

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
1035995 2024-07-27T00:30:49 Z Requiem Sailing Race (CEOI12_race) C++17
40 / 100
145 ms 18656 KB
#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, cntEdge = 0;
vector<int> g[MAXN], backEdge[MAXN];

void extract(int curId){
     int num = 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);
                 cntEdge++;
//                 cout << curId << ' ' << num << endl;
             }
             else break;

             num = 0;

         }
     }
}

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 and cntEdge <= 500;
    }

    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

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: In function 'void subtask2::solve()':
race.cpp:241:35: warning: variable 'bestI' set but not used [-Wunused-but-set-variable]
  241 |          int res = subtask1::res, bestI = subtask1::bestI;
      |                                   ^~~~~
race.cpp: At global scope:
race.cpp:268:1: warning: ISO C++ forbids declaration of 'main' with no type [-Wreturn-type]
  268 | main()
      | ^~~~
race.cpp: In function 'int main()':
race.cpp:272:16: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  272 |         freopen(TASKNAME".inp","r",stdin);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~
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".out","w",stdout);
      |         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 8 ms 18268 KB Output is correct
2 Incorrect 9 ms 18268 KB Unexpected end of file - int32 expected
3 Incorrect 11 ms 18268 KB Unexpected end of file - int32 expected
4 Incorrect 11 ms 18268 KB Unexpected end of file - int32 expected
5 Correct 11 ms 18268 KB Output is correct
6 Incorrect 6 ms 14432 KB Unexpected end of file - int32 expected
7 Correct 15 ms 18524 KB Output is correct
8 Incorrect 7 ms 14556 KB Unexpected end of file - int32 expected
9 Correct 17 ms 18520 KB Output is correct
10 Correct 27 ms 18524 KB Output is correct
11 Correct 20 ms 18572 KB Output is correct
12 Incorrect 7 ms 14424 KB Unexpected end of file - int32 expected
13 Incorrect 6 ms 14684 KB Unexpected end of file - int32 expected
14 Correct 102 ms 18640 KB Output is correct
15 Incorrect 7 ms 14936 KB Unexpected end of file - int32 expected
16 Incorrect 7 ms 15196 KB Unexpected end of file - int32 expected
17 Incorrect 7 ms 14828 KB Unexpected end of file - int32 expected
18 Correct 145 ms 18656 KB Output is correct
19 Incorrect 7 ms 15192 KB Unexpected end of file - int32 expected
20 Incorrect 7 ms 15196 KB Unexpected end of file - int32 expected