Submission #447618

# Submission time Handle Problem Language Result Execution time Memory
447618 2021-07-27T06:47:33 Z blue Long Mansion (JOI17_long_mansion) C++17
100 / 100
1868 ms 143648 KB
#include <iostream>
#include <vector>
#include <stack>
#include <set>
using namespace std;

const int INF = 1e9;

const int maxN = 500'000;
const int lgN = 19;




int N;
vector<int> C(1+maxN+1);
vector<int> key_pos_list[1+maxN+1];




vector<int> left_key_pos(1+maxN+1);
vector<int> right_key_pos(1+maxN+1);




vector<int> go_left(1+maxN+1);
vector<int> go_right(1+maxN+1);



bool queryAdj(int i, int j)
{
    if(i == 0 || i == N+1) return 1;

    if(j == i+1) return (go_left[i] <= right_key_pos[i]);
    else if(j == i-1) return (left_key_pos[i] <= go_right[i]);
    else
    {
        cout << "ERROR\n";
        return 0;
    }
}



vector<int> left_reach(1+maxN+1);
vector<int> right_reach(1+maxN+1);







struct segtree
{
    int l;
    int r;

    int mn = 0;
    int mx = 0;

    segtree* left = NULL;
    segtree* right = NULL;

    segtree()
    {
        ;
    }

    segtree(int L, int R)
    {
        l = L;
        r = R;
        if(l == r) return;
        int m = (l+r)/2;
        left = new segtree(l, m);
        right = new segtree(m+1, r);
    }

    void update(int I, int V)
    {
        if(I < l || r < I) return;
        else if(l == r)
        {
            mn = mx = V;
        }
        else
        {
            left->update(I, V);
            right->update(I, V);
            mn = min(left->mn, right->mn);
            mx = max(left->mx, right->mx);
        }
    }

    int rangemax(int L, int R)
    {
        if(R < l || r < L) return -INF;
        else if(L <= l && r <= R)
        {
            return mx;
        }
        else
        {
            return max(left->rangemax(L, R), right->rangemax(L, R));
        }
    }

    int rangemin(int L, int R)
    {
        if(R < l || r < L) return INF;
        else if(L <= l && r <= R)
        {
            return mn;
        }
        else
        {
            return min(left->rangemin(L, R), right->rangemin(L, R));
        }
    }
};





int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);

//PART 0: INPUT
    cin >> N;

    for(int i = 1; i+1 <= N; i++)
        cin >> C[i];

    for(int k = 1; k <= N; k++)
        key_pos_list[k].push_back(0);

    for(int i = 1; i <= N; i++)
    {
        int B;
        cin >> B;

        for(int j = 1; j <= B; j++)
        {
            int A;
            cin >> A;

            key_pos_list[A].push_back(i);
        }
    }

    for(int k = 1; k <= N; k++)
        key_pos_list[k].push_back(N+1);









//PART 1: left_key_pos, right_key_pos;

    left_key_pos[1] = N+1;
    for(int i = 2; i <= N; i++)
    {
        int ind = -1;
        for(int bit = lgN; bit >= 0; bit--)
        {
            if(ind + (1 << bit) >= key_pos_list[ C[i-1] ].size()) continue;
            if(key_pos_list[ C[i-1] ][ind + (1 << bit)] >= i) continue;
            ind += (1 << bit);
        }
        ind++;
        left_key_pos[i] = key_pos_list[ C[i-1] ][ind];
    }

    segtree left_key_segtree(1, N);
    for(int i = 1; i <= N; i++) left_key_segtree.update(i, left_key_pos[i]);


    right_key_pos[N] = 0;
    for(int i = N-1; i >= 1; i--)
    {
        int ind = -1;
        for(int bit = lgN; bit >= 0; bit--)
        {
            if(ind + (1 << bit) >= key_pos_list[ C[i] ].size()) continue;
            if(key_pos_list[ C[i] ][ind + (1 << bit)] > i) continue;
            ind += (1 << bit);
        }
        right_key_pos[i] = key_pos_list[ C[i] ][ind];
    }

    segtree right_key_segtree(1, N);
    for(int i = 1; i <= N; i++) right_key_segtree.update(i, right_key_pos[i]);











// PART 2: go_left, go_right;

    stack<int> left_wall;
    for(int i = 1; i <= N; i++)
    {
        // cerr << "i = " << i << '\n';
        left_wall.push(i);
        while(left_key_pos[ left_wall.top() ] <= i)
            left_wall.pop();

        go_left[i] = left_wall.top();
    }

    stack<int> right_wall;
    for(int i = N; i >= 1; i--)
    {
        // cerr << "i = " << i << '\n';
        right_wall.push(i);
        while(right_key_pos[ right_wall.top() ] >= i)
            right_wall.pop();

        go_right[i] = right_wall.top();
    }

    // cerr << "\n\n";
    // for(int i = 1; i <= N; i++) cerr << go_left[i] << ' ' << go_right[i] << '\n';





    //left_wall and right_wall are now used differently.


//PART 3: left_reach

    vector<int> tmp;


    while(!left_wall.empty()) left_wall.pop();

    for(int i = 1; i <= N; i++)
    {
        // cerr << "\n\n\n";
        // cerr << "i = " << i << '\n';
        if(queryAdj(i, i-1) == 0) //i is start of LC
        {
            left_reach[i] = i;
            left_wall.push(i);

            // cerr << "case 1: " << left_reach[i] << '\n';
        }
        else if(queryAdj(i+1, i) == 1) //i is in the middle of LC
        {
            if(queryAdj(i, i+1) == 1)
            {
                //compute i+1, then solve for this
                tmp.push_back(i);
            }
            else
            {
                left_reach[i] = go_left[i];

                for(int t: tmp) left_reach[t] = left_reach[i];
                tmp.clear();
            }
        }
        else
        {
            // cerr << "case 2 \n";
            int curr_go_right = go_right[i];
            // while(left_key_pos[ left_wall.top() ] <= go_right[i]) //do a binary search!!!!!
            //     left_wall.pop();

            // cerr << left_wall.top() << ' ' << left_key_pos[left_wall.top()] << ' ' << curr_go_right << '\n';
            for(int bit = lgN; bit >= 0; bit--)
            {
                int new_go_right = curr_go_right + (1 << bit);
                if(new_go_right > N) continue;

                if(left_wall.top() <= right_key_segtree.rangemin(i, new_go_right - 1))
                    curr_go_right = new_go_right;
            }


            while(left_key_pos[ left_wall.top() ] <= curr_go_right)
            {
                left_wall.pop();

                for(int bit = lgN; bit >= 0; bit--)
                {
                    int new_go_right = curr_go_right + (1 << bit);
                    if(new_go_right > N) continue;

                    if(left_wall.top() <= right_key_segtree.rangemin(i, new_go_right - 1))
                        curr_go_right = new_go_right;
                }

                // cerr << left_wall.top() << ' ' << left_key_pos[left_wall.top()] << ' ' << curr_go_right << '\n';
            }

            left_reach[i] = left_wall.top();
            for(int t: tmp) left_reach[t] = left_reach[i];
            tmp.clear();
        }
    }








//PART 4: right_reach


    tmp.clear();

    while(!right_wall.empty()) right_wall.pop();

    for(int i = N; i >= 1; i--)
    {
        // cerr << "\n\n\n";
        // cerr << "i = " << i << '\n';
        if(queryAdj(i, i+1) == 0)
        {
            right_reach[i] = i;
            right_wall.push(i);
        }
        else if(queryAdj(i-1, i) == 1)
        {
            if(queryAdj(i, i-1) == 1)
            {
                tmp.push_back(i);
            }
            else
            {
                right_reach[i] = go_right[i];

                for(int t: tmp) right_reach[t] = right_reach[i];
                tmp.clear();
            }
        }
        else
        {
            int curr_go_left = go_left[i];

            for(int bit = lgN; bit >= 0; bit--)
            {
                int new_go_left = curr_go_left - (1 << bit);
                if(new_go_left < 1) continue;

                if(right_wall.top() >= left_key_segtree.rangemax(new_go_left + 1, i))
                    curr_go_left = new_go_left;
            }

            // while(right_key_pos[ right_wall.top() ] >= i) //do a binary search!!!!!
            //     right_wall.pop();

            // cerr << right_wall.top() << ' ' << right_key_pos[ right_wall.top() ] << ' ' << curr_go_left << '\n';

            while(right_key_pos[ right_wall.top() ] >= curr_go_left)
            {
                right_wall.pop();
                for(int bit = lgN; bit >= 0; bit--)
                {
                    int new_go_left = curr_go_left - (1 << bit);
                    if(new_go_left < 1) continue;

                    if(right_wall.top() >= left_key_segtree.rangemax(new_go_left + 1, i))
                        curr_go_left = new_go_left;
                }

                // cerr << right_wall.top() << ' ' << right_key_pos[ right_wall.top() ] << ' ' << curr_go_left << '\n';
            }


            right_reach[i] = right_wall.top();
            for(int t: tmp) right_reach[t] = right_reach[i];
            tmp.clear();
        }
    }






    // cerr << "\n\n\n";



//PART 5: QUERIES
    // for(int i = 1; i <= N; i++) cerr << i << ": " << left_reach[i] << ' ' << right_reach[i] << '\n';


    int Q;
    cin >> Q;

    for(int q = 1; q <= Q; q++)
    {
        int X, Y;
        cin >> X >> Y;

        if(left_reach[X] <= Y && Y <= right_reach[X])
            cout << "YES\n";
        else
            cout << "NO\n";
    }
}

Compilation message

long_mansion.cpp: In function 'int main()':
long_mansion.cpp:177:33: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  177 |             if(ind + (1 << bit) >= key_pos_list[ C[i-1] ].size()) continue;
      |                ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
long_mansion.cpp:195:33: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  195 |             if(ind + (1 << bit) >= key_pos_list[ C[i] ].size()) continue;
      |                ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Verdict Execution time Memory Grader output
1 Correct 22 ms 26188 KB Output is correct
2 Correct 22 ms 26484 KB Output is correct
3 Correct 22 ms 26840 KB Output is correct
4 Correct 21 ms 26188 KB Output is correct
5 Correct 16 ms 26188 KB Output is correct
6 Correct 20 ms 26256 KB Output is correct
7 Correct 18 ms 26248 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 22 ms 26188 KB Output is correct
2 Correct 22 ms 26484 KB Output is correct
3 Correct 22 ms 26840 KB Output is correct
4 Correct 21 ms 26188 KB Output is correct
5 Correct 16 ms 26188 KB Output is correct
6 Correct 20 ms 26256 KB Output is correct
7 Correct 18 ms 26248 KB Output is correct
8 Correct 127 ms 27760 KB Output is correct
9 Correct 134 ms 27824 KB Output is correct
10 Correct 133 ms 28100 KB Output is correct
11 Correct 138 ms 28632 KB Output is correct
12 Correct 120 ms 27724 KB Output is correct
13 Correct 157 ms 27860 KB Output is correct
14 Correct 122 ms 27976 KB Output is correct
15 Correct 125 ms 28028 KB Output is correct
16 Correct 117 ms 28216 KB Output is correct
17 Correct 134 ms 27880 KB Output is correct
18 Correct 122 ms 27912 KB Output is correct
19 Correct 123 ms 27932 KB Output is correct
20 Correct 128 ms 28036 KB Output is correct
21 Correct 121 ms 28248 KB Output is correct
22 Correct 125 ms 28008 KB Output is correct
23 Correct 127 ms 27752 KB Output is correct
24 Correct 149 ms 27728 KB Output is correct
25 Correct 130 ms 27716 KB Output is correct
26 Correct 127 ms 27716 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 519 ms 51324 KB Output is correct
2 Correct 496 ms 51092 KB Output is correct
3 Correct 429 ms 50984 KB Output is correct
4 Correct 487 ms 51408 KB Output is correct
5 Correct 492 ms 51116 KB Output is correct
6 Correct 357 ms 50632 KB Output is correct
7 Correct 246 ms 50664 KB Output is correct
8 Correct 237 ms 50632 KB Output is correct
9 Correct 242 ms 50688 KB Output is correct
10 Correct 239 ms 50724 KB Output is correct
11 Correct 253 ms 50756 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 22 ms 26188 KB Output is correct
2 Correct 22 ms 26484 KB Output is correct
3 Correct 22 ms 26840 KB Output is correct
4 Correct 21 ms 26188 KB Output is correct
5 Correct 16 ms 26188 KB Output is correct
6 Correct 20 ms 26256 KB Output is correct
7 Correct 18 ms 26248 KB Output is correct
8 Correct 127 ms 27760 KB Output is correct
9 Correct 134 ms 27824 KB Output is correct
10 Correct 133 ms 28100 KB Output is correct
11 Correct 138 ms 28632 KB Output is correct
12 Correct 120 ms 27724 KB Output is correct
13 Correct 157 ms 27860 KB Output is correct
14 Correct 122 ms 27976 KB Output is correct
15 Correct 125 ms 28028 KB Output is correct
16 Correct 117 ms 28216 KB Output is correct
17 Correct 134 ms 27880 KB Output is correct
18 Correct 122 ms 27912 KB Output is correct
19 Correct 123 ms 27932 KB Output is correct
20 Correct 128 ms 28036 KB Output is correct
21 Correct 121 ms 28248 KB Output is correct
22 Correct 125 ms 28008 KB Output is correct
23 Correct 127 ms 27752 KB Output is correct
24 Correct 149 ms 27728 KB Output is correct
25 Correct 130 ms 27716 KB Output is correct
26 Correct 127 ms 27716 KB Output is correct
27 Correct 519 ms 51324 KB Output is correct
28 Correct 496 ms 51092 KB Output is correct
29 Correct 429 ms 50984 KB Output is correct
30 Correct 487 ms 51408 KB Output is correct
31 Correct 492 ms 51116 KB Output is correct
32 Correct 357 ms 50632 KB Output is correct
33 Correct 246 ms 50664 KB Output is correct
34 Correct 237 ms 50632 KB Output is correct
35 Correct 242 ms 50688 KB Output is correct
36 Correct 239 ms 50724 KB Output is correct
37 Correct 253 ms 50756 KB Output is correct
38 Correct 598 ms 120672 KB Output is correct
39 Correct 690 ms 143648 KB Output is correct
40 Correct 489 ms 98184 KB Output is correct
41 Correct 1006 ms 139104 KB Output is correct
42 Correct 361 ms 50504 KB Output is correct
43 Correct 299 ms 50456 KB Output is correct
44 Correct 524 ms 73480 KB Output is correct
45 Correct 468 ms 73476 KB Output is correct
46 Correct 503 ms 73592 KB Output is correct
47 Correct 246 ms 50688 KB Output is correct
48 Correct 247 ms 50500 KB Output is correct
49 Correct 389 ms 73552 KB Output is correct
50 Correct 413 ms 73580 KB Output is correct
51 Correct 471 ms 73644 KB Output is correct
52 Correct 856 ms 72884 KB Output is correct
53 Correct 1361 ms 95868 KB Output is correct
54 Correct 1868 ms 118000 KB Output is correct
55 Correct 1368 ms 107156 KB Output is correct