Submission #1098889

#TimeUsernameProblemLanguageResultExecution timeMemory
1098889PacybwoahWerewolf (IOI18_werewolf)C++17
100 / 100
472 ms92920 KiB
#include "werewolf.h"
#include<iostream>
#include<utility>
#include<algorithm>
#include<vector>
using namespace std;
namespace{
    int n, q;
    vector<int> bases;
    struct node{
        int par, sz, lid, rid;
        node(int a, int b, int c, int d){
            par = a;
            sz = b;
            lid = c;
            rid = d;
        }
    };
    struct dsust{
        vector<node> dsu;
        vector<int> l, r, w, vec, pos;
        vector<vector<int>> st;
        dsust(){
            for(int i = 0; i <= n; i++) dsu.push_back(node(i, 1, i, i));
            l.resize(n + 1);
            r.resize(n + 1);
            w.resize(n + 1);
            vec.resize(n + 1);
            pos.resize(n + 1);
            st.resize(19, vector<int>(n + 1));
            fill(l.begin(), l.end(), -1);
            fill(r.begin(), r.end(), -1);
        }
        int query(int x){
            if(x == dsu[x].par) return x;
            dsu[x].par = query(dsu[x].par);
            return dsu[x].par;
        }
        void unite(int a, int b, int val){
            a = query(a);
            b = query(b);
            if(a == b) return;
            if(dsu[a].sz < dsu[b].sz) swap(a, b);
            dsu[b].par = a;
            dsu[a].sz += dsu[b].sz;
            w[dsu[a].rid] = val;
            r[dsu[a].rid] = dsu[b].lid;
            l[dsu[b].lid] = dsu[a].rid;
            dsu[a].rid = dsu[b].rid;
        }
        void build(){
            int cur = dsu[query(1)].lid;
            for(int i = 1; i <= n; i++){
                vec[i] = cur;
                pos[cur] = i;
                st[0][i] = w[cur];
                cur = r[cur];
            }
            for(int i = 1; i < 19; i++){
                for(int j = 1; j < n; j++){
                    st[i][j] = max(st[i - 1][j], st[i - 1][min(n - 1, j + (1 << (i - 1)))]);
                }
            }
        }
        int query(int ql, int qr){
            int len = qr - ql + 1;
            return max(st[bases[len]][ql], st[bases[len]][qr - (1 << bases[len]) + 1]);
        }
        pair<int, int> get_rng(int id, int val){
            pair<int, int> ans;
            id = pos[id];
            int bsl = id, bsr = n;
            while(bsl < bsr){
                int mid = ((bsl + bsr) >> 1) + 1;
                if(query(id, mid - 1) > val) bsr = mid - 1;
                else bsl = mid;
            }
            ans.second = bsl;
            bsl = 1, bsr = id;
            while(bsl < bsr){
                int mid = (bsl + bsr) >> 1;
                if(query(mid, id - 1) > val) bsl = mid + 1;
                else bsr = mid;
            }
            ans.first = bsl;
            return ans;
        }
    };
    struct bit{
        vector<int> vec;
        bit(int _n){
            vec.resize(_n + 1);
        }
        void modify(int pos){
            while(pos <= n){
                vec[pos]++;
                pos += (pos & -pos);
            }
        }
        int query(int pos){
            int ans = 0;
            while(pos > 0){
                ans += vec[pos];
                pos -= (pos & -pos);
            }
            return ans;
        }
    };
}
std::vector<int> check_validity(int N, std::vector<int> X, std::vector<int> Y, std::vector<int> S, std::vector<int> E, std::vector<int> L, std::vector<int> R) {
    n = N;
    q = (int)S.size();
    bases.resize(n);
    int now = 0;
    for(int i = 1; i < n; i++){
        if((1 << (now + 1)) <= i) now++;
        bases[i] = now;
    }
    int m = (int)X.size();
    vector<pair<pair<int, int>, int>> maxedges, minedges;
    auto cmp = [&](pair<pair<int, int>, int> a, pair<pair<int, int>, int> b){
        return a.second < b.second;
    };
    for(int i = 0; i < m; i++){
        X[i]++;
        Y[i]++;
        maxedges.push_back(make_pair(make_pair(X[i], Y[i]), -min(X[i], Y[i])));
        minedges.push_back(make_pair(make_pair(X[i], Y[i]), max(X[i], Y[i])));
    }
    sort(maxedges.begin(), maxedges.end(), cmp);
    sort(minedges.begin(), minedges.end(), cmp);
    dsust maxst = dsust(), minst = dsust();
    for(auto &[x, val]: maxedges){
        auto &[u, v] = x;
        maxst.unite(u, v, val);
    }
    for(auto &[x, val]: minedges){
        auto &[u, v] = x;
        minst.unite(u, v, val);
    }
    maxst.build();
    minst.build();
    vector<pair<int, int>> qpos(q);
    vector<vector<pair<int, int>>> sweep(n + 1);
    vector<int> ans(q);
    for(int i = 0; i < q; i++){
        S[i]++;
        E[i]++;
        L[i]++;
        R[i]++;
        qpos[i] = minst.get_rng(E[i], R[i]);
        auto [l, r] = maxst.get_rng(S[i], -L[i]);
        sweep[l - 1].emplace_back(i, -1);
        sweep[r].emplace_back(i, 1);
    }
    bit b(n);
    for(int i = 1; i <= n; i++){
        b.modify(minst.pos[maxst.vec[i]]);
        for(auto &[id, val]: sweep[i]){
            ans[id] += val * (b.query(qpos[id].second) - b.query(qpos[id].first - 1));
        }
    }
    vector<int> anss;
    for(int i = 0; i < q; i++){
        if(ans[i] > 0) anss.push_back(1);
        else anss.push_back(0);
    }
    return anss;
}
// g++ -std=c++17 -fsanitize=undefined -fsanitize=address -Wall -Wextra -Wshadow grader.cpp werewolf.cpp -o run
/*
6 6 3
5 1
1 2
1 3
3 4
3 0
5 2
4 2 1 2
4 2 2 2
5 4 3 4
*/
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...