Submission #381031

#TimeUsernameProblemLanguageResultExecution timeMemory
381031ponytailRace (IOI11_race)C++17
0 / 100
10 ms16108 KiB
#include "bits/stdc++.h"
using namespace std;
#ifdef ONLINE_JUDGE
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
typedef tree<int, null_type, less<int>, rb_tree_tag, tree_order_statistics_node_update> OST;
#endif
#define int long long
#define double long double
#define mp make_pair
#define fi first
#define se second
#define pb push_back
#define all(a) a.begin(),a.end()
const int MOD = 1000000007;
const int MOD2 = 998244353;
const int BIG = 1197423052705914509LL;
mt19937 rng((int) std::chrono::steady_clock::now().time_since_epoch().count());
const int MAXN = 2e5 + 10;
const int NO_OPERATION = 69420420420LL;
const int is_query = -BIG;
struct line {
    int m, b;
    mutable function<const line*()> succ;
    bool operator<(const line& rhs) const {
        if (rhs.b != is_query) return m < rhs.m;
        const line* s = succ();
        if (!s) return 0;
        int x = rhs.m;
        return b - s->b < (s->m - m) * x;
    }
};
struct dynamic_hull : public multiset<line> { 
    const int inf = BIG;
    bool bad(iterator y) {
        auto z = next(y);
        if (y == begin()) {
            if (z == end()) return 0;
            return y->m == z->m && y->b <= z->b;
        }
        auto x = prev(y);
        if (z == end()) return y->m == x->m && y->b <= x->b;
        int v1 = (x->b - y->b);
        if (y->m == x->m) v1 = x->b > y->b ? inf : -inf;
        else v1 /= (y->m - x->m);
        int v2 = (y->b - z->b);
        if (z->m == y->m) v2 = y->b > z->b ? inf : -inf;
        else v2 /= (z->m - y->m);
        return v1 >= v2;
    }
    void insert_line(int m, int b) {
        auto y = insert({m,b});
        y->succ = [=] { return next(y) == end() ? 0 : &*next(y); };
        if (bad(y)) { erase(y); return; }
        while (next(y) != end() && bad(next(y))) erase(next(y));
        while (y != begin() && bad(prev(y))) erase(prev(y));
    }
    int eval(int x) {
        auto l = *lower_bound((line) { x, is_query });
        return l.m * x + l.b;
    }
};
struct auxiliary_tree{
    int n;
    vector<int>ori[MAXN];
    vector<int>storelatest;
    int tin[MAXN], tout[MAXN], dep[MAXN], cor[MAXN];
    bool imp[MAXN];
    int run=0;
    vector<int>euler;
    vector<vector<pair<int,int> > >lca_table;
    int lef[MAXN], rig[MAXN];
    void dfs(int node,int prev,int de){
        dep[node]=de;
        tin[node]=++run;
        cor[tin[node]]=node;
        euler.pb(node);
        for(int i=0;i<ori[node].size();i++){
            if(ori[node][i]!=prev){
                dfs(ori[node][i],node,de+1);
                euler.pb(node);
            }
        }
        tout[node]=++run;
    }
    void find_all_lcas(){
        int k=log2(2*n-1);
        lca_table.resize(k+1);
        for(int i=0;i<k+1;i++){
            lca_table[i].resize(2*n-1);
        }
        for(int i=0;i<2*n-1;i++){
            lca_table[0][i]=mp(dep[euler[i]],euler[i]);
        }
        for(int i=1;i<=k;i++){
            for(int j=0;j<2*n-1;j++){
                if(j+(1<<(i-1))>=2*n-1)continue;
                if(lca_table[i-1][j].fi<lca_table[i-1][j+(1<<(i-1))].fi){
                    lca_table[i][j].fi=lca_table[i-1][j].fi;
                    lca_table[i][j].se=lca_table[i-1][j].se;
                }
                else{
                    lca_table[i][j].fi=lca_table[i-1][j+(1<<(i-1))].fi;
                    lca_table[i][j].se=lca_table[i-1][j+(1<<(i-1))].se;
                }
            }
        }
        for(int i=0;i<MAXN;i++) lef[i]=-1;
        for(int i=0;i<2*n-1;i++){
            if(lef[euler[i]]==-1){
                lef[euler[i]]=i;
            }
            rig[euler[i]]=i;
        }
    }
    bool isParent(int u,int v){
        return tin[u]<tin[v] && tout[v]<tout[u];
    }
    public:
    vector<int>adj[MAXN];
    int root;
    int lcadep(int x,int y){
        if(lef[x]>rig[y]){
            swap(x,y);
        }
        int k=log2(rig[y]-lef[x]+1);
        return min(lca_table[k][lef[x]].fi,lca_table[k][rig[y]-(1<<k)+1].fi);
    }
    int lcaidx(int x,int y){
        if(lef[x]>rig[y]){
            swap(x,y);
        }
        int k=log2(rig[y]-lef[x]+1);
        if(lca_table[k][lef[x]].fi<lca_table[k][rig[y]-(1<<k)+1].fi){
            return lca_table[k][lef[x]].se;
        }
        else{
            return lca_table[k][rig[y]-(1<<k)+1].se;
        }
    }
    void base(int x,int rt,vector<int>y[]){
        n=x;
        for(int i=1;i<=n;i++){
            ori[i]=y[i];
        }
        dfs(rt,-1,0);
        find_all_lcas();
    }
    void build(vector<int>g){
        for(int i=0;i<g.size();i++){
            g[i]=tin[g[i]];
        }
        sort(all(g));
        for(int i=0;i<g.size();i++){
            g[i]=cor[g[i]];
        }
        int k=g.size();
        for(int i=0;i<k-1;i++){
            g.pb(lcaidx(g[i],g[i+1]));
        }
        for(int i=0;i<g.size();i++){
            g[i]=tin[g[i]];
        }
        sort(all(g));
        for(int i=0;i<g.size();i++){
            g[i]=cor[g[i]];
        }
        g.erase(unique(all(g)),g.end());
        for(int i=0;i<g.size();i++){
            imp[g[i]]=1;
            storelatest.pb(g[i]);
        }
        stack<int>vert;
        vert.push(g[0]);
        for(int i=1;i<g.size();i++){
            int u=g[i];
            while(vert.size()>1 && isParent(vert.top(),u)==0){
                int sto=vert.top();
                vert.pop();
                adj[vert.top()].pb(sto);
            }
            vert.push(u);
        }
        while(vert.size()>1){
            int sto=vert.top();
            vert.pop();
            adj[vert.top()].pb(sto);
        }
        root=vert.top();
    }
    void clear(){
        for(int i=0;i<storelatest.size();i++){
            imp[storelatest[i]]=0;
            adj[storelatest[i]].clear();
        }
        storelatest.clear();
    }
};
struct custom_hash{
    static uint64_t splitmix64(uint64_t x){
        x += 0x9e3779b97f4a7c15;
        x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9;
        x = (x ^ (x >> 27)) * 0x94d049bb133111eb;
        return x ^ (x >> 31);
    }
    size_t operator()(uint64_t a) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        return splitmix64(a + FIXED_RANDOM);
    }
    template<class T> size_t operator()(T a) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        hash<T> x;
        return splitmix64(x(a) + FIXED_RANDOM);
    }
    template<class T, class H> size_t operator()(pair<T, H> a) const {
        static const uint64_t FIXED_RANDOM = chrono::steady_clock::now().time_since_epoch().count();
        hash<T> x;
        hash<H> y;
        return splitmix64(x(a.f) * 37 + y(a.s) + FIXED_RANDOM);
    }
};
template<class T, class H>using umap=unordered_map<T,H,custom_hash>;
int sz[MAXN], maxsz[MAXN], n, k;
vector<pair<int,int> >adj[MAXN];
unordered_map<int,int> f[MAXN];
const int MAXK = 10000010;
int exist[MAXK], exist2[MAXK];
int ans = 1e9;
int whole_size;
int number_of_operations = 0;
int dfs0(int node,int prev){
    sz[node]=1;
    number_of_operations++;
    for(pair<int,int>x:adj[node]){
        if(x.se==-1)continue;
        if(x.fi==prev)continue;
        int d=dfs0(x.fi,node);
        sz[node]+=d;
    }
    return sz[node];
}
int dfs(int node,int prev){
    sz[node]=1;
    maxsz[node]=0;
    number_of_operations++;
    for(pair<int,int> x:adj[node]){
        if(x.se==-1) continue;
        if(x.fi==prev) continue;
        int d=dfs(x.fi,node);
        sz[node]+=d;
        maxsz[node]=max(maxsz[node],d);
    }
    maxsz[node]=max(maxsz[node],whole_size-sz[node]);
    return sz[node];
}
queue<int>ntv;
vector<int>all;
void wheewhoowhee(int node,int prev){
    all.pb(node);
    for(pair<int,int>x:adj[node]){
        if(x.se==-1)continue;
        if(x.fi==prev)continue;
        wheewhoowhee(x.fi,node);
    }
}
int divide(){
    all.clear();
    wheewhoowhee(ntv.front(),-1);
    for(int i:all){
        sz[i]=0;
        maxsz[i]=1e9;
        number_of_operations++;
    }
    whole_size=dfs0(ntv.front(),-1);
    dfs(ntv.front(),-1);
    ntv.pop();
    int centroid=0, e=1e9;
    for(int i:all){
        if(e>maxsz[i]){
            e=maxsz[i];
            centroid=i;
        }
    }
    for(pair<int,int> x:adj[centroid]){
        if(x.se==-1) continue;
        ntv.push(x.fi);
    }
    return centroid;
}
queue<int>used, used2, used3;
void dfs2(int node,int prev,int cur,int dep){
//  cout <<cur <<"\n";
    if(cur>=1 && cur<MAXK && exist2[cur]==1e9){
//        cout << "FUCK\n";
        used.push(cur);
        used3.push(cur);
    }
    if(cur>=1 && cur<MAXK){
        exist2[cur]=min(exist2[cur],dep);
    }
    for(pair<int,int>x:adj[node]){
        if(x.se==-1) continue;
        if(x.fi==prev) continue;
        dfs2(x.fi,node,cur+x.se,dep+1);
    }
}
void conquer(int root){
    while(used2.size()){
        exist[used2.front()]=1e9;
        used2.pop();
    }
    for(int i=0;i<adj[root].size();i++){
        if(adj[root][i].se==-1) continue;
        int sto=adj[root][i].se;
        adj[root][i].se=-1;
        adj[adj[root][i].fi][f[adj[root][i].fi][root]].se=-1;
        dfs2(adj[root][i].fi,-1,sto,1);
        while(used3.size()){
//            cout << "E "<<i<<" "<<used3.front()<<"\n";
            if(k==used3.front()){
                ans=min(ans,exist2[used3.front()]);
            }
            if(k-used3.front()>=1 && k-used3.front()<MAXK && exist[k-used3.front()]!=1e9){
//                cout << "F "<<exist[k-used3.front()] << " " << exist2[used3.front()] << "\n";
                ans=min(ans,exist[k-used3.front()]+exist2[used3.front()]);
//                cout << "G "<<ans << "\n";
            }
            used3.pop();
        }
        while(used.size()){
            if(exist[used.front()]==1e9) used2.push(used.front());
            exist[used.front()]=min(exist[used.front()],exist2[used.front()]);
//            cout << "exist "<<used.front()<<" "<<exist[used.front()]<<"\n";
            exist2[used.front()]=1e9;
            used.pop();
        }
    }
}
signed best_path(signed N,signed K,signed h[][2],signed l[]){
    int n=N, k=K;
    for(int i=1;i<=n;i++) exist[i]=1e9, exist2[i]=1e9;
    for(int i=1;i<n;i++){
        int u=h[i-1][0],v=h[i-1][1],w=l[i-1];
        //cin >> u >> v >> w;
        u++, v++;
        int U=adj[u].size();
        int V=adj[v].size();
        f[u][v]=U;
        f[v][u]=V;
        adj[u].pb({v,w});
        adj[v].pb({u,w});
    }
    ntv.push(1);
    while(ntv.size()){
        conquer(divide());
    }
    return (ans==1e9 ? -1 : ans);
}

Compilation message (stderr)

race.cpp: In member function 'void auxiliary_tree::dfs(long long int, long long int, long long int)':
race.cpp:79:22: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   79 |         for(int i=0;i<ori[node].size();i++){
      |                     ~^~~~~~~~~~~~~~~~~
race.cpp: In member function 'void auxiliary_tree::build(std::vector<long long int>)':
race.cpp:151:22: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  151 |         for(int i=0;i<g.size();i++){
      |                     ~^~~~~~~~~
race.cpp:155:22: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  155 |         for(int i=0;i<g.size();i++){
      |                     ~^~~~~~~~~
race.cpp:162:22: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  162 |         for(int i=0;i<g.size();i++){
      |                     ~^~~~~~~~~
race.cpp:166:22: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  166 |         for(int i=0;i<g.size();i++){
      |                     ~^~~~~~~~~
race.cpp:170:22: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  170 |         for(int i=0;i<g.size();i++){
      |                     ~^~~~~~~~~
race.cpp:176:22: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  176 |         for(int i=1;i<g.size();i++){
      |                     ~^~~~~~~~~
race.cpp: In member function 'void auxiliary_tree::clear()':
race.cpp:193:22: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<long long int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  193 |         for(int i=0;i<storelatest.size();i++){
      |                     ~^~~~~~~~~~~~~~~~~~~
race.cpp: In function 'void conquer(long long int)':
race.cpp:313:18: warning: comparison of integer expressions of different signedness: 'long long int' and 'std::vector<std::pair<long long int, long long int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
  313 |     for(int i=0;i<adj[root].size();i++){
      |                 ~^~~~~~~~~~~~~~~~~
race.cpp: In function 'int best_path(int, int, int (*)[2], int*)':
race.cpp:341:14: warning: unused variable 'k' [-Wunused-variable]
  341 |     int n=N, k=K;
      |              ^
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...