제출 #1343855

#제출 시각아이디문제언어결과실행 시간메모리
1343855SmuggingSpunWind Turbines (EGOI25_windturbines)C++20
100 / 100
822 ms46732 KiB
#include<bits/stdc++.h>
#define taskname "D"
using namespace std;
typedef long long ll;
template<class T>void maximize(T& a, T b){
  if(a < b){
    a = b;
  }
}
const int lim = 1e5 + 5;
int n, m, q, u[lim], v[lim], w[lim], lab[lim];
int find_set(int i){
  while(i != lab[i]){
    i = lab[i] = lab[lab[i]];
  }
  return i;
}
bool merge(int i, int j){
  if((i = find_set(i)) != (j = find_set(j))){
    lab[j] = i;
    return true;
  }
  return false;
}
namespace sub1{
  bool check_subtask(){
    if(m != n - 1){
      return false;
    }
    for(int i = 0; i < m; i++){
      if(u[i] != i || v[i] != i + 1){
        return false;
      }
    }
    return true;
  }
  void solve(){
    vector<ll>f(n);
    f[0] = 0;
    for(int i = 1; i < n; i++){
      f[i] = f[i - 1] + w[i - 1];
    }
    for(int _ = 0; _ < q; _++){
      int l, r;
      cin >> l >> r;
      cout << f[n - 1] - f[r] + f[l] << "\n";
    }
  }
}
namespace sub2{
  void solve(){
    vector<int>p(m);
    iota(p.begin(), p.end(), 0);
    sort(p.begin(), p.end(), [&] (int i, int j){
      return w[i] < w[j];
    });
    iota(lab, lab + n, 0);
    for(int _ = 0; _ < q; _++){
      int l, r;
      cin >> l >> r;
      iota(lab, lab + n, 0);
      for(int i = l; i < r; i++){
        merge(i, r);
      }
      ll ans = 0;
      for(int& i : p){
        if(merge(u[i], v[i])){
          ans += w[i];
        }
      }
      cout << ans << "\n";
    }
  }
}
vector<pair<int, int>>query;
const int LG = 17;
namespace sub3{
  bool check_subtask(){
    for(auto& [l, r] : query){
      if(r != l + 1){
        return false;
      }
    }
    return true;
  }
  vector<pair<int, int>>up[LG];
  void solve(){
    vector<int>p(m);
    iota(p.begin(), p.end(), 0);
    sort(p.begin(), p.end(), [&] (int i, int j){
      return w[i] < w[j];
    });
    iota(lab, lab + n, 0);
    ll mst = 0;
    vector<vector<int>>tree(n);
    for(int& i : p){
      if(merge(u[i], v[i])){
        tree[u[i]].push_back(i);
        tree[v[i]].push_back(i);
        mst += w[i];
      }
    }
    vector<int>h(n);
    up[0].assign(n, make_pair(h[0] = 0, 0));
    function<void(int)>dfs;
    dfs = [&] (int s){
      for(int& i : tree[s]){
        int d = u[i] ^ v[i] ^ s;
        if(d != up[0][s].first){
          h[d] = h[up[0][d].first = s] + 1;
          up[0][d].second = w[i];
          dfs(d);
        }
      }
    };
    dfs(0);
    for(int i = 1; i < LG; i++){
      up[i].resize(n);
      for(int j = 0; j < n; j++){
        up[i][j] = make_pair(up[i - 1][up[i - 1][j].first].first, max(up[i - 1][j].second, up[i - 1][up[i - 1][j].first].second));
      }
    }
    auto get_max_weight = [&] (int u, int v){
      if(h[u] < h[v]){
        swap(u, v);
      }
      int ans = 0;
      for(int i = 0, k = h[u] - h[v]; i < LG; i++){
        if(k >> i & 1){
          maximize(ans, up[i][u].second);
          u = up[i][u].first;
        }
      }
      if(u == v){
        return ans;
      }
      for(int i = LG - 1; i > -1; i--){
        if(up[i][u].first != up[i][v].first){
          maximize(ans, max(up[i][u].second, up[i][v].second));
          u = up[i][u].first;
          v = up[i][v].first;
        }
      }
      return max(ans, max(up[0][u].second, up[0][v].second));
    };
    for(auto& [l, r] : query){
      cout << mst - get_max_weight(l, r) << "\n";
    }
  }
}
namespace sub4567{
  int thld = 0, lead[lim], par[lim << 1], head[lim << 1], siz[lim << 1], low[lim << 1], tail[lim << 1], val[lim << 1];
  ll fval[lim << 1], bit[lim], ans[lim << 1];
  void update(int p, ll x){
    for(p = n - p; p <= n; p += p & -p){
      bit[p] += x;
    }
  }
  ll get(int p){
    ll ans = 0;
    for(p = n - p; p > 0; p -= p & -p){
      ans += bit[p];
    }
    return ans;
  }
  pair<int, int>child[lim << 1];
  vector<int>g[lim << 1], qid[lim];
  void dfs(int s){
    siz[s] = 1;
    for(int& d : g[s]){
      dfs(d);
      siz[par[d] = s] += siz[d];
    }
  }
  void hld(int s){
    low[s] = ++thld;
    int heavy = -1;
    for(int& d : g[s]){
      if(heavy == -1 || siz[d] > siz[heavy]){
        heavy = d;
      }
    }
    if(heavy != -1){
      head[heavy] = head[s];
      hld(heavy);
      for(int& d : g[s]){
        if(d != heavy){
          hld(head[d] = d);
        }
      }
    }
    tail[s] = thld;
  }
  struct Data{
    int l, r, k;
    Data(){}
    Data(int _l, int _r, int _k) : l(_l), r(_r), k(_k) {}
    friend bool operator <(const Data a, const Data b){
      return a.l < b.l;
    }
  };
  set<Data>s;
  void split_set(int p){
    auto it = prev(s.upper_bound(Data(p, -1, -1)));
    if(p > it->l && p <= it->r){
      Data x = *it;
      s.erase(it);
      s.insert(Data(x.l, p - 1, x.k));
      s.insert(Data(p, x.r, x.k));
    }
  }
  void work(int l, int r, int k){
    split_set(l);
    split_set(r + 1);
    vector<Data>change;
    for(auto it = s.lower_bound(Data(l, -1, -1)); it != s.end() && it->l <= r; it++){
      change.push_back(*it);
    }
    s.erase(s.lower_bound(Data(l, -1, -1)), s.upper_bound(Data(r, -1, -1)));
    for(Data& it : change){
      update(it.k, -(fval[it.r] - fval[it.l - 1]));
      update(k, fval[it.r] - fval[it.l - 1]);
    }
    s.insert(Data(l, r, k));
  } 
  void solve(){
    for(int i = 0; i < n; i++){
      val[lead[i] = lab[i] = i] = 0;
    }
    vector<int>eid(m);
    iota(eid.begin(), eid.end(), 0);
    sort(eid.begin(), eid.end(), [&] (int i, int j){
      return w[i] < w[j];
    });
    ll mst_sum = 0;
    int N = n - 1;
    for(int& i : eid){
      if(find_set(u[i]) != find_set(v[i])){
        g[++N].push_back(lead[find_set(u[i])]);
        g[N].push_back(lead[find_set(v[i])]);
        mst_sum += (val[lead[lab[find_set(v[i])] = find_set(u[i])] = N] = w[i]);
      }
    }
    dfs(N);
    hld(head[N] = par[N] = N); 
    for(int i = fval[0] = 0; i <= N; i++){
      fval[low[i]] = val[par[i]] - val[i];
    }
    for(int i = 1; i <= thld; i++){
      fval[i] += fval[i - 1];
    }
    for(int i = 0; i <= N; i++){
      s.insert(Data(low[i], low[i], -1));
    }
    for(int i = 0; i < q; i++){
      qid[query[i].second].push_back(i);
    }
    for(int r = 0; r < n; r++){
      int x = r;
      while(x != N){
        work(low[head[x]], low[x], r);
        x = par[head[x]];
      }
      for(int& i : qid[r]){
        ans[i] = mst_sum - get(query[i].first) + val[N];  
      }
    }
    for(int i = 0; i < q; i++){
      cout << ans[i] << "\n";
    }
  }
}
int main(){
	ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	if(fopen(taskname".inp", "r")){
		freopen(taskname".inp", "r", stdin);
	}
  cin >> n >> m >> q;
  for(int i = 0; i < m; i++){
    cin >> u[i] >> v[i] >> w[i];
  }
  if(sub1::check_subtask()){
    sub1::solve();
  }
  else if(max({n, m, q}) <= 2000){
    sub2::solve();
  }
  else{
    for(int i = 0; i < q; i++){
      int l, r;
      cin >> l >> r;
      query.push_back(make_pair(l, r));
    }
    if(sub3::check_subtask()){
      sub3::solve();
    }
    else{
      sub4567::solve();
    }
  }
}

컴파일 시 표준 에러 (stderr) 메시지

Main.cpp: In function 'int main()':
Main.cpp:276:24: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)' declared with attribute 'warn_unused_result' [-Wunused-result]
  276 |                 freopen(taskname".inp", "r", stdin);
      |                 ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
#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...
#Verdict Execution timeMemoryGrader output
Fetching results...