Submission #1323551

#TimeUsernameProblemLanguageResultExecution timeMemory
1323551SmuggingSpunRoad Closures (APIO21_roads)C++20
100 / 100
457 ms247872 KiB
#include "roads.h"
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int lim = 1e5 + 5;
int n;
vector<int>u, v, w, g[lim];
namespace sub1{
  vector<ll>solve(){
    sort(w.begin(), w.end(), greater<int>());
    vector<ll>ans(n);
    ans[n - 1] = 0;
    for(int i = n - 2; i > -1; i--){
      ans[i] = ans[i + 1] + w[i];
    }
    return ans;
  }
}
namespace sub2{
  bool check_subtask(){
    for(int i = 0; i + 1 < n; i++){
      if(u[i] != i || v[i] != i + 1){
        return false;
      }
    }
    return true;
  }
  vector<ll>solve(){
    vector<ll>dp(2, 0), ndp(2);
    for(int i = 0; i + 1 < n; i++, swap(dp, ndp)){
      ndp[0] = dp[1];
      ndp[1] = min(dp[0], dp[1]) + w[i];
    }
    vector<ll>ans(n, 0);
    ans[0] = accumulate(w.begin(), w.end(), 0LL);
    ans[1] = min(dp[0], dp[1]);
    return ans;
  }
}
namespace sub34{
  vector<ll>solve(){
    vector<ll>ans(n);
    ans[0] = accumulate(w.begin(), w.end(), 0LL);
    for(int k = 1; k < n; k++){
      function<pair<ll, ll>(int, int)>dfs;
      dfs = [&] (int s, int p){
        vector<pair<ll, ll>>child;
        for(int& i : g[s]){
          int d = u[i] ^ v[i] ^ s;
          if(d != p){
            pair<ll, ll>dv = dfs(d, s);
            child.push_back(make_pair(dv.first, min(dv.first, dv.second) + w[i]));
          }
        }
        pair<ll, ll>ans = make_pair(0, 0);
        ll sum = 0;
        int need = int(g[s].size()) - k;
        vector<ll>dif;
        for(auto& [u, v] : child){
          if(v <= u){
            need--;
            sum += v;
          }
          else{
            sum += u;
            dif.push_back(v - u);
          }
        }
        sort(dif.begin(), dif.end());
        for(int i = 0; i < need; i++){
          sum += dif[i];
        }
        ans.first = ans.second = sum;
        if(need > 0){
          ans.second -= dif[need - 1];
        }
        return ans;
      };
      ans[k] = dfs(0, -1).first;
    }
    return ans;
  }
}
namespace sub5{
  vector<ll>solve(){
    vector<ll>ans(n, 0);
    ans[0] = accumulate(w.begin(), w.end(), 0LL);
    vector<int>par(n), h(n), deg(n);
    function<void(int)>dfs;
    dfs = [&] (int s){
      for(int& i : g[s]){
        int d = u[i] ^ v[i] ^ s;
        if(d != par[s]){
          h[d] = h[par[d] = s] + 1;
          dfs(d);
        }
      }
    };
    dfs(par[0] = h[0] = 0);
    vector<vector<int>>vertex(n);
    for(int i = 0; i < n; i++){
      vertex[deg[i] = g[i].size()].push_back(i);
    }
    set<pair<int, int>>s;
    for(int k = n - 1; k > 0; k--){
      for(int& i : vertex[k]){
        s.insert(make_pair(-h[i], i));
      }
      for(auto& [foo, u] : s){
        deg[u] = g[u].size();
      }
      for(auto& [foo, u] : s){
        if(deg[u] > k){
          ans[k] += deg[u] - k;
          deg[par[u]]--;
        }
      }
    }
    return ans;
  }
}
namespace sub67{
  struct Node{
    int cnt, c[2];
    ll s;
    Node(){
      c[cnt = s = 0] = c[1] = -1;
    }
  };
  struct Data{
    vector<Node>t;
    Data(){
      t.push_back(Node());
    }
    void insert(int x){
      for(int i = 29, r = 0; i > -1; i--){
        bool N = x >> i & 1;
        if(t[r].c[N] == -1){
          t[r].c[N] = t.size();
          t.push_back(Node());
        }
        t[r = t[r].c[N]].s += x;
        t[r].cnt++;
      }
    }
    void remove(int x){
      for(int i = 29, r = 0; i > -1; i--){
        t[r = t[r].c[x >> i & 1]].s -= x;
        t[r].cnt--;
      }
    }
    ll get_sum(int k){
      ll ans = 0;
      int r = 0, val = 0;
      for(int i = 29; i > -1; i--){
        if(t[r].c[0] == -1){
          r = t[r].c[1];
          val |= 1 << i;
        }
        else if(t[r].c[1] == -1){
          r = t[r].c[0];
        }
        else if(t[t[r].c[0]].cnt <= k){
          ans += t[t[r].c[0]].s;
          k -= t[t[r].c[0]].cnt;
          r = t[r].c[1];
          val |= 1 << i;
        }
        else{
          r = t[r].c[0];
        }
      }
      return ans + ll(val) * k;
    }
    int get_kth(int k){
      int ans = 0;
      for(int i = 29, r = 0; i > -1; i--){
         if(t[r].c[0] == -1){
          r = t[r].c[1];
          ans |= 1 << i;
        }
        else if(t[r].c[1] == -1){
          r = t[r].c[0];
        }
        else if(t[t[r].c[0]].cnt < k){
          k -= t[t[r].c[0]].cnt;
          r = t[r].c[1];
          ans |= 1 << i;
        }
        else{
          r = t[r].c[0];
        }
      }
      return ans;
    }
  };
  Data ds[lim];
  bitset<lim>vis;
  vector<ll>solve(){
    for(int i = 0; i < n; i++){
      sort(g[i].begin(), g[i].end(), [&] (int x, int y){
        return g[u[x] ^ v[x] ^ i].size() > g[u[y] ^ v[y] ^ i].size();
      });
      for(int& j : g[i]){
        ds[i].insert(w[j]);
      }
    }
    vector<ll>ans(n, 0);
    ans[0] = accumulate(w.begin(), w.end(), 0LL);
    vector<int>sbd(n);
    iota(sbd.begin(), sbd.end(), 0);
    sort(sbd.begin(), sbd.end(), [&] (int i, int j){
      return g[i].size() > g[j].size();
    });
    for(int k = n - 1; k > 0; k--){
      function<pair<ll, ll>(int, int)>dfs;
      dfs = [&] (int s, int p){
        vis[s] = true;
        int need = int(g[s].size()) - k;
        pair<ll, ll>ans = make_pair(0, 0);
        vector<int>cache;
        for(int& i : g[s]){
          int d = u[i] ^ v[i] ^ s;
          if(g[d].size() <= k){
            break;
          }
          if(d != p){
            ds[s].remove(w[i]);
            ds[d].remove(w[i]);
            pair<ll, ll>child = dfs(d, s);
            if((child.second = min(child.first, child.second) + w[i]) <= child.first){
              need--;
              ans.first += child.second;
            }
            else{
              ans.first += child.first;
              cache.push_back(child.second - child.first);
              ds[s].insert(cache.back());
            }
          }
        }
        if(need > 0){
          ans.second = (ans.first += ds[s].get_sum(need)) - ds[s].get_kth(need);
        }
        else{
          ans.second = ans.first;
        }
        for(int& x : cache){
          ds[s].remove(x);
        }
        for(int& i : g[s]){
          int d = u[i] ^ v[i] ^ s;
          if(g[d].size() <= k){
            break;
          }
          if(d != p){
            ds[s].insert(w[i]);
            ds[d].insert(w[i]);
          }
        }
        return ans;
      };
      for(int& i : sbd){
        if(g[i].size() <= k){
          break;
        }
        vis[i] = false;
      }
      for(int& i : sbd){
        if(g[i].size() <= k){
          break;
        }
        if(!vis[i]){
          ans[k] += dfs(i, -1).first;
        }
      }
    }
    return ans;
  }
}
vector<ll>minimum_closure_costs(int N, vector<int>U, vector<int>V, vector<int>W){
  n = N;
  swap(u, U);
  swap(v, V);
  swap(w, W);
  for(int i = 0; i + 1 < n; i++){
    g[u[i]].push_back(i);
    g[v[i]].push_back(i);
  }
  if(*max_element(u.begin(), u.end()) == 0){
    return sub1::solve();
  }
  if(sub2::check_subtask()){
    return sub2::solve();
  }
  if(n <= 2000){
    return sub34::solve();
  }
  if(*max_element(w.begin(), w.end()) == 1){
    return sub5::solve();
  }
  return sub67::solve();
}
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...