제출 #1328673

#제출 시각아이디문제언어결과실행 시간메모리
1328673animal_migrationTourism (JOI23_tourism)C++17
41 / 100
5051 ms62984 KiB
#include <bits/stdc++.h>
using namespace std;
// #define int long long
#define pii pair<int,int>
#define fi first
#define se second
#define all(x) x.begin(),x.end()
#define rall(x) x.rbegin(),x.rend()
#define pb push_back
#define eb emplace_back
#define rep(x,y,z) for (int x=y;x<z;x++)

int par(int x, vector<int> &dsu){
  if (dsu[x]<0) return x;
  return par(dsu[x],dsu);
}

signed main(){
  cin.tie(nullptr)->ios::sync_with_stdio(0);
  //init
  int p2[30], l2[1000000];
  p2[0]=1;
  rep(i,1,30) p2[i]=(p2[i-1]<<1);
  l2[1]=0;
  rep(i,2,1000000) l2[i]=l2[i>>1]+1;
  //input
  int n,m,q;
  cin>>n>>m>>q;
  vector<vector<int>> G(n);
  rep(i,1,n){
    int u,v;
    cin>>u>>v;
    u--; v--;
    G[u].pb(v);
    G[v].pb(u);
  }
  vector<int> dd(n), ff(n), lf(n), st(n);
  vector<int> ord(n);
  vector<int> ss(n),tt(n);
  vector<int> vv;
  int tim=0, tim1=0;
  function<void(int,int)> dfs=[&](int u, int f){
    ord[tim]=u;
    st[u]=tim++;
    ff[u]=f;
    ss[u]=tt[u]=tim1++;
    vv.pb(u);
    int p=lf[ff[u]], q=lf[p];
    if (u!=f&&dd[q]-dd[p]==dd[p]-dd[ff[u]]) lf[u]=q;
    else lf[u]=ff[u];
    for (int v:G[u]){
      if (v==f) continue;
      dd[v]=dd[u]+1;
      dfs(v,u);
      tt[u]=tim1++;
      vv.pb(u);
    }
  };
  dfs(0,0);
  vector<vector<int>> spa(20,vector<int>(tim1));
  vector<vector<int>> pos(20,vector<int>(tim1));
  rep(i,0,tim1){
    spa[0][i]=dd[vv[i]];
    pos[0][i]=vv[i];
  }
  for (int i=1;i<20;i++){
    for (int j=0;j<=tim1-p2[i];j++){
      if (spa[i-1][j]<spa[i-1][j+p2[i-1]]){
        spa[i][j]=spa[i-1][j];
        pos[i][j]=pos[i-1][j];
      }else{
        spa[i][j]=spa[i-1][j+p2[i-1]];
        pos[i][j]=pos[i-1][j+p2[i-1]];
      }
    }
  }
  function<int(int,int)> cal=[&](int u, int v){
    if (st[u]>st[v]) swap(u,v);
    int sta=ss[u];
    int end=tt[v];
    int len=(end-sta+1);
    // cout<<sta<<' '<<end<<' '<<len<<'\n';
    int lca;
    if (spa[l2[len]][sta]<spa[l2[len]][end-p2[l2[len]]+1]){
      lca=pos[l2[len]][sta];
    }else{
      lca=pos[l2[len]][end-p2[l2[len]]+1];
    }
    // cout<<u+1<<' '<<v+1<<" -> "<<lca+1<<'\n';
    return dd[u]+dd[v]-dd[lca]*2+1;
  };
  vector<int> A(m);
  vector<int> cop(n,0);
  rep(i,0,m) cin>>A[i], A[i]--, cop[A[i]]++;
  rep(i,0,n){
    if (cop[i]==0){
      A.pb(i); m++;
      cop[i]++;
    }
  }
  // cout<<m<<'\n';
  // rep(i,0,m) cout<<A[i]<<' ';
  // cout<<'\n';
  //precompute lca, dfs order
  //build dsu
  int sz=n;
  vector<int> ll(n);
  vector<int> rr(n);
  vector<int> wl(n), wr(n), hl(n), hr(n);
  //rem function
  #define vit vector<int>::iterator
  vector<int> prv(n), nxt(n);
  stack<pair<vit,int>> row;
  function<void(int,bool)> rem=[&](int x, bool o){
    // cout<<x+1<<' '<<sz<<" -> ";
    x=st[x];
    int lp,rp;
    lp=prv[x];
    rp=nxt[x];
    // cout<<"*"<<ord[x]+1<<' '<<ord[lp]+1<<' '<<ord[rp]+1<<'\n';
    // cout<<cal(ord[x],ord[lp])<<' '<<cal(ord[x],ord[rp])<<' '<<cal(ord[lp],ord[rp])<<'\n';
    sz-=(cal(ord[x],ord[lp])+cal(ord[x],ord[rp])-cal(ord[lp],ord[rp]))/2;
    if (o) row.push({nxt.begin()+prv[x],nxt[prv[x]]});
    if (o) row.push({prv.begin()+nxt[x],prv[nxt[x]]});
    nxt[prv[x]]=rp;
    prv[nxt[x]]=lp;
    // cout<<sz<<'\n';
  };
  //input qry, process
  int bz=700;
  int bn=(m+bz-1)/bz;
  struct Q { int l; int r; int id; };
  auto com=[](Q a, Q b){
    return a.r>b.r;
  };
  vector<vector<Q>> qry(bn);
  rep(i,0,q){
    int l,r;
    cin>>l>>r;
    l--; r--;
    qry[l/bz].pb({l,r,i});
  }
  rep(i,0,bn){
    sort(all(qry[i]),com);
  }
  //sqrt decom
  vector<int> ans(q);
  rep(i,0,bn){
    rep(j,0,n){
      prv[j]=(j-1+n)%n;
      nxt[j]=(j+1)%n;
    }
    sz=n;
    vector<int> fre(cop);
    int ql=0, qr=m-1;
    while (ql<i*bz){
      fre[A[ql]]--;
      if (fre[A[ql]]==0) rem(A[ql],0);
      ql++;
      // cout<<ql<<' '<<qr<<' '<<sz<<'\n';
    }
    for (auto [l,r,id]:qry[i]){
      // cout<<ql<<' '<<qr<<" -> ";
      while (qr>r){
        fre[A[qr]]--;
        if (fre[A[qr]]==0) rem(A[qr],0);
        qr--;
        // cout<<ql<<' '<<qr<<' '<<sz<<'\n';
      }
      int oz=sz;
      while (ql<l){
        fre[A[ql]]--;
        if (fre[A[ql]]==0) rem(A[ql],1);
        ql++;
        // cout<<ql<<' '<<qr<<' '<<sz<<'\n';
      }
      ans[id]=sz;
      sz=oz;
      // cout<<ql<<' '<<qr<<'\n';
      while (!row.empty()){
        auto [it,v]=row.top();
        row.pop();
        *it=v;
      }
      while (ql>i*bz){
        ql--;
        fre[A[ql]]++;
      }
      // cout<<ql<<' '<<qr<<' '<<sz<<'\n';
    }
  }
  //output
  rep(i,0,q){
    cout<<ans[i]<<'\n';
  }
  return 0;
}
#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...