Submission #1237068

#TimeUsernameProblemLanguageResultExecution timeMemory
1237068guanexPrize (CEOI22_prize)C++17
10 / 100
1412 ms331820 KiB
#include<bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;

//data structures

typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<ll> vll;
typedef vector<ld> vld;
typedef pair<long long, long long> pll;
typedef pair<char, int> ci;
typedef pair<string, int> si;
typedef vector<int> vi;
typedef vector<string> vs;
typedef vector<vector<int>> vvi;
#define pb push_back
#define pf push_front
#define popb pop_back
#define popf pop_front
#define sz(a) ((int)a.size())
#define fi first
#define se second
#define whole(v) v.begin(), v.end()
#define rwhole(v) v.rbegin(), v.rend()
#define fro front
#define pqueue priority_queue
#define ubound upper_bound
#define lbound lower_bound
#define beg(v) v.begin()

//bit operations

int flip(int x){
    return ~(x) ^ (1 << 32);
}

int allon(int x){
    return (1LL << x) - 1;
}

bool bit(ll a, ll i){
    return (1LL << i) & a;
}

#define llpc(x) __builtin_popcountll(x)
#define ipc(x) __builtin_popcount(x)
#define iclz(x) __builtin_clz(x)
#define llclz(x) __builtin_clzll(x)
#define ictz(x) __builtin_ctz(x)
#define llctz(x) __builtin_ctzll(x)

//answers

#define cYES cout << "YES" << endl
#define cYes cout << "Yes" << endl
#define cyes cout << "yes" << endl
#define cNO cout << "NO" << endl
#define cNo cout << "No" << endl
#define cno cout << "no" << endl
#define ipsb cout << -1 << endl

const ll mod2 = 998244353;
const ll mod = 1000000007;
const int inf = int(1e9); // ll inf = ll(1e18);

// read arr vec matr etc

#define fill(x, y) memset(x, y, sizeof(x))

void read(vector<int> &x){
    for(auto &e:x) cin >> e;
}

void sread(vector<string> &x){
    for(auto &e:x) cin >> e;
}

void mread(vector<vector<int>> &p, int nnn, int mmm){
    for(int i = 0; i < nnn; ++i){
        vector<int> pp;
        for(int j = 0; j < mmm; ++j){
            int wq; cin >> wq; pp.pb(wq);
        }
        p.pb(pp);
    }
}

//mt19937 rng(chrono::steady_clock::now().time_since_epoch().count()); //high quality random number generator using time as seed
//int random(int l, int r){return uniform_int_distribution<int>(l,r)(rng);} //returns a randomb number between [l, r]

// Solution

struct sparse{
    vvi st;
    sparse(vi &a){
        st.assign(sz(a), vi(21, 0));
        for(int i = 0; i < sz(a); ++i){
            if(a[i] == -1){
                st[i][0] = i;
            }else
                st[i][0] = a[i]-1;
        }
        for(int bit = 1; bit < 21; ++bit){
            for(int i = 0; i < sz(a); ++i){
                st[i][bit] = st[st[i][bit-1]][bit-1];
            }
        }
    }
    int lca(int a, int b, vi &depth){
        if(a == b){
            return a;
        }
        if(depth[a] < depth[b])swap(a, b); // a is deeper
        int distancia = depth[a] - depth[b];
        for(int bit = 20; bit >= 0; --bit){
            if(distancia & (1 << bit)){
                a = st[a][bit];
            }
        }
        if(a == b){
            return a;
        }
        for(int bit = 20; bit >= 0; --bit){
            if(st[a][bit] != st[b][bit]){
                a = st[a][bit];
                b = st[b][bit];
            }
        }
        return st[a][0];
    }
};

/*struct sparsesum{
    vvi st;
    vvi sum;
    sparsesum(){
        
    }
    sparsesum(vii &a){
        st.assign(sz(a), vi(21, 0));
        sum.assign(sz(a), vi(21, 0));
        for(int i = 0; i < sz(a); ++i){
            if(a[i].fi == -1){
                st[i][0] = i;
                sum[i][0] = 0;
            }else{
                st[i][0] = a[i].fi;
                sum[i][0] = a[i].se;
            }
        }
        for(int bit = 1; bit < 21; ++bit){
            for(int i = 0; i < sz(a); ++i){
                st[i][bit] = st[st[i][bit-1]][bit-1];
                sum[i][bit] = sum[i][bit-1] + sum[st[i][bit-1]][bit-1]; 
            }
        }
    }
    ii lca(int a, int b, vi &depth){
        if(a == b){
            return {0, 0};
        }
        if(depth[a] < depth[b])swap(a, b); // a is deeper
        int ans = 0;
        int an = 0;
        //cout << a << " " << b << endl;
        for(int bit = 20; bit >= 0; --bit){
            if(depth[st[a][bit]] > depth[b]){
                ans += sum[a][bit];
                a = st[a][bit];
            }
        }
        ans += sum[a][0];
        a = st[a][0]; // same depth 
        //cout << ans <<  " " << an << " " << a << endl;
        if(a == b){
            return {ans, an};
        }
        for(int bit = 20; bit >= 0; --bit){
            if(st[a][bit] != st[b][bit]){
                ans += sum[a][bit];
                an += sum[b][bit];
                a = st[a][bit];
                b = st[b][bit];
            }
        }
        //cout << ans << " " << an << endl;
        return (ii){ans + sum[a][0], an + sum[b][0]};
    }
};


struct graph{
    vi depths;
    vii ed;
    sparsesum stt;
    graph(vi &depth){
        depths = depth;
        ed.assign(sz(depth), {-1, -1});
    }
    void join(int v, int u, int vans, int uans, sparse &st){
        int lca = st.lca(u, v, depths);
        //cout << u << " " << v << " " << lca << " " << depths[u] << " " << depths[v] << " " << depths[lca] << endl;
        ed[v] = {lca, vans};
        //cout << ed[u].fi << " " << ed[u].se << " " << ed[v].fi << " " << ed[v].se << endl;
        if(ed[u] == ii(-1, -1)){
            ed[u] = {lca, uans};
            if(ed[u].first == u){
                ed[u] = {-1, -1};
            }
            if(ed[v].first == v){
                ed[v] = {-1, -1};
            }
            return;
        }
        while(ed[u].first != -1 && depths[u] > depths[lca] && (depths[ed[u].first] > depths[lca])){
            uans -= ed[u].second;
            u = ed[u].first;
        }
        if(lca == ed[u].first || lca == u){
            if(ed[u].first == u){
                ed[u] = {-1, -1};
            }
            if(ed[v].first == v){
                ed[v] = {-1, -1};
            }
            return;
        }
        if(ed[u] == ii(-1, -1)){
            ed[u] = {lca, uans};
        }else{
            ii fat = ed[u];
            ed[u] = {lca, uans};
            if(fat == (ii){-1, -1}){
                ed[lca] = {-1, -1};
            }else{
                ed[lca] = {fat.first, fat.second - uans};
            }
        }
        //cout << ed[u].fi << " " << ed[u].se << " " << ed[v].fi << " " << ed[v].se << endl;
        if(ed[u].first == u){
            ed[u] = {-1, -1};
        }
        if(ed[v].first == v){
            ed[v] = {-1, -1};
        }
    }
    void create(){
        sparsesum sttt(ed);
        stt = sttt;
    }
    int answer(int u, int v){
        ii ans = stt.lca(u, v, depths);
        return ans.fi + ans.se;
    }
};*/

vi nodes;

void dfs(int no, int fat, int depth, vi &depths, vvi &ed){
    nodes.pb(no);
    depths[no] = depth; 
    for(auto e:ed[no]){
        if(e == fat){
            continue;
        }
        dfs(e, no, depth+1, depths, ed);
    }
}

void tc(){
    int n, k, q, t; cin >> n >> k >> q >> t;
    vi a(n), b(n);
    read(a); read(b);
    vvi eda(n);
    int root = 0;
    int roo = 0;
    for(int i = 0; i < n; ++i){
        if(a[i] == -1){
            root = i;
        }else{
            eda[a[i]-1].pb(i);
            eda[i].pb(a[i]-1);
        }
    }
    vi rootdist(n, 0);
    rootdist[root] = 0;
    vi da(n);
    vi db(n);
    vvi edb(n);
    for(int i = 0; i < n; ++i){
        if(b[i] == -1){
            roo = i;
        }else{
            edb[b[i]-1].pb(i);
            edb[i].pb(b[i]-1);
        }
    }
    dfs(roo, -1, 0, db, edb);
    nodes.clear();
    dfs(root, -1, 0, da, eda);
    while(sz(nodes) > k){
        nodes.pop_back();
    }
    sparse sta(a);
    if(sz(nodes) != k){
        exit(0);
    }
    for(int i = 0; i < sz(nodes); ++i){
        cout << nodes[i]+1 << ((i != sz(nodes)-1)? " ":"\n");
    }
    //fflush(stdout);
    //cout.flush();
    cout << flush;
    vii queries;
    for(int i = 1; i < sz(nodes); ++i){
        cout << "? " << nodes[i]+1 << " " << nodes[0]+1 << "\n";
        //cout.flush();
        queries.pb({i, 0});
    }
    cout << "!\n";
    //fflush(stdout);
    //cout.flush();
    cout << flush;
    //graph setree(db);
    for(int i = 0; i < sz(queries); ++i){
        int e, f, g, h; cin >> e >> f >> g >> h;
        int u = nodes[queries[i].fi];
        int v = nodes[queries[i].se];
        int uu = u;
        int vv = v;
        int fitreev = sta.lca(u, v, da);
        rootdist[u] = rootdist[fitreev] + e; // calculates all distance from root on the first tree(the joint one)
        //setree.join(uu, vv, g, h, stb); //uses graph structure to create the lca tree from the second tree, join erase a big edge, add a node, and join 2 small edges to the initial points
    }

    //setree.create(); //crate sum sparse table
    vii query;
    for(int i = 0; i < t; ++i){
        int u, v; cin >> u >> v;
        u--;
        v--;
        int lca = sta.lca(u, v, da);
        ii ans;
        ans.fi = rootdist[u] + rootdist[v] - 2 * rootdist[lca];
        //ans.se = setree.answer(u, v);
        query.pb(ans);
    }
    for(auto e:query){
        cout << e.fi << " " << e.fi << "\n";
    }
    //fflush(stdout);
    //cout.flush();
    cout << flush;
}

int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(0); cout.tie(0);
    int t = 1;
    while(t--){
        tc();
    }
}

Compilation message (stderr)

Main.cpp: In function 'int flip(int)':
Main.cpp:38:22: warning: left shift count >= width of type [-Wshift-count-overflow]
   38 |     return ~(x) ^ (1 << 32);
      |                    ~~^~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...