Submission #719568

#TimeUsernameProblemLanguageResultExecution timeMemory
719568keisuke6Bridges (APIO19_bridges)C++14
16 / 100
1010 ms71748 KiB
#include <bits/stdc++.h>
using namespace std;
#define int long long
bool f(vector<int> S){
  for(int x:S)if(x==1) return false;
  return true;
}
struct Unionfind{
  vector<int> par, siz;
  //初期化
  Unionfind(int n) : par(n,-1) , siz(n,1) {}
  int root(int x) {
    if(par[x] == -1) return x;
    else return par[x] = root(par[x]);
  }
  bool issame(int x,int y) {
    return root(x) == root(y);
  }
  bool unite(int x, int y){
    x = root(x); y = root(y);
    if(x ==  y) return false;
    if(siz[x] < siz[y]) swap(x,y);
    par[y] =  x;
    siz[x] += siz[y];
    return  true;
  }
  int size(int x) {
    return siz[root(x)];
  }
};
template <typename T>
struct RMQ {
    const T INF = numeric_limits<T>::max();
    int n;         // 葉の数
    vector<T> dat; // 完全二分木の配列
    RMQ(int n_) : n(), dat(n_ * 4, INF) { // 葉の数は 2^x の形
        int x = 1;
        while (n_ > x) {
            x *= 2;
        }
        n = x;
    }
    void update(int i, T x) {
        i += n - 1;
        dat[i] = x;
        while (i > 0) {
            i = (i - 1) / 2;  // parent
            dat[i] = min(dat[i * 2 + 1], dat[i * 2 + 2]);
        }
    }
    // the minimum element of [a,b)
    T query(int a, int b) { return query_sub(a, b, 0, 0, n); }
    T query_sub(int a, int b, int k, int l, int r) {
        if (r <= a || b <= l) {
            return INF;
        } else if (a <= l && r <= b) {
            return dat[k];
        } else {
            T vl = query_sub(a, b, k * 2 + 1, l, (l + r) / 2);
            T vr = query_sub(a, b, k * 2 + 2, (l + r) / 2, r);
            return min(vl, vr);
        }
    }
};
signed main(){
  int N,M,Q;
  cin>>N>>M;
  RMQ<int> seg(N-1);
  vector<vector<int>> G(N);
  unordered_map<int,int> m;
  map<int,multiset<int>> s;
  map<int,pair<int,int>> ed;
  map<int,int> edc;
  for(int i=0;i<M;i++){
    int a,b,c;
    cin>>a>>b>>c;
    a--;
    b--;
    seg.update(i,c);
    ed[i] = {a,b};
    edc[i] = c;
    m[a*N+b] = max(c,m[a*N+b]);
    m[b*N+a] = max(c,m[a*N+b]);
    s[a*N+b].insert(c);
    s[b*N+a].insert(c);
    G[a].push_back(b);
    G[b].push_back(a);
  }
  cin>>Q;
  vector<int> T(Q),A(Q),B(Q);
  for(int i=0;i<Q;i++){
    cin>>T[i]>>A[i]>>B[i];
    A[i]--;
  }
  if(f(T)){
    Unionfind uf(N);
    vector<pair<int,int>> S(Q);
    for(int i=0;i<Q;i++) S[i] = {B[i],A[i]};
    map<int,int> ans;
    sort(S.rbegin(),S.rend());
    vector<tuple<int,int,int>> C = {};
    for(int i=0;i<N;i++)for(int j:G[i]){
      C.push_back({m[i*N+j],i,j});
    }
    sort(C.rbegin(),C.rend());
    int ind = 0;
    for(int i=0;i<Q;i++){
      while(ind != 2*(int)(m.size())){
        int a,b,c;
        tie(a,b,c) = C[ind];
        if(a < S[i].first) break;
        uf.unite(b,c);
        ind++;
      }
      ans[S[i].first*N+S[i].second] = uf.size(S[i].second);
    }
    for(int i=0;i<Q;i++) cout<<ans[B[i]*N+A[i]]<<endl;
    return 0;
  }
  if(max({N,M,Q}) <= 10000){
    for(int i=0;i<Q;i++){
      if(T[i] == 1){
        int a,b;
        tie(a,b) = ed[A[i]];
        s[a*N+b].erase(s[a*N+b].find(edc[A[i]]));
        s[a*N+b].insert(B[i]);
        swap(a,b);
        s[a*N+b].erase(s[a*N+b].find(edc[A[i]]));
        s[a*N+b].insert(B[i]);
        edc[A[i]] = B[i];
        continue;
      }
      queue<int> q;
      q.push(A[i]);
      vector<bool> seen(N,false);
      seen[A[i]] = true;
      while(!q.empty()){
        int pos = q.front();
        q.pop();
        for(int x:G[pos]){
          if(seen[x] || *s[pos*N+x].rbegin() < B[i]) continue;
          seen[x] = true;
          q.push(x);
        }
      }
      int count = 0;
      for(int i=0;i<N;i++) count += seen[i];
      cout<<count<<endl;
    }
    return 0;
  }
  for(int i=0;i<Q;i++){
    if(T[i] == 1){
      seg.update(A[i],B[i]);
      continue;
    }
    int ans = 1;
    if(A[i]){
      int l = 0, r = A[i]-1;
      while(r-l > 1){
        int mid = (l+r)/2;
        if(seg.query(mid,A[i]) >= B[i]) r = mid;
        else l = mid;
      }
      if(seg.query(A[i]-1,A[i]) < B[i]) ans += 0;
      else if(seg.query(0,A[i]) >= B[i]) ans += A[i];
      else ans += A[i]-r;
    }
    if(A[i] != N-1){
      int l = A[i]+1, r = N;
      while(r-l > 1){
        int mid = (l+r)/2;
        if(seg.query(A[i],mid) >= B[i]) l = mid;
        else r = mid;
      }
      if(seg.query(A[i],A[i]+1) < B[i]) ans += 0;
      else if(seg.query(A[i],N-1) >= B[i]) ans += N-1-A[i];
      else ans += l-A[i];
    }
    cout<<ans<<endl;
  }
}
#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...