Submission #1228698

#TimeUsernameProblemLanguageResultExecution timeMemory
1228698minhpkRegions (IOI09_regions)C++20
60 / 100
7700 ms45240 KiB
#include <bits/stdc++.h>

using namespace std;
int a,b,c;
vector <int> z[200001];
int t[200001];
int sl[25001];
int block;
int check[200001];
int mark[200001];
int cur=0;
int cnt[200001];
int sta[200001];
int fin[200001];
int rev[200001];
int child[200001];
int tour;
int big[200001];

int pre[630][630];
int res[200001];
int cnt1[500][25001];
int cnt2[500][25001];

void predfs(int i,int parent){
    tour++;
    sta[i]=tour;
    rev[tour]=i;
    child[i]=1;
    big[i]=-1;

    for (auto p:z[i]){
         if (p==parent){
            continue;
         }

         predfs(p,i);
         child[i]+=child[p];
         if (big[i]==-1 || child[big[i]]<child[p]){
             big[i]=p;
         }
    }

    fin[i]=tour;
}

void dfs(int i,int parent,bool keep){
    for (auto p:z[i]){
         if (p==parent || p==big[i]){
             continue;
         }
         dfs(p,i,0);
    }
    if (big[i]!=-1){
         dfs(big[i],i,1);
    }

    for (auto p:z[i]){
         if (p==parent || p==big[i]){
            continue;
         }
         for (int j=sta[p];j<=fin[p];j++){
              int x=rev[j];
              if (mark[t[x]]){
                  cnt[mark[t[x]]]++;
              }
         }
    }

    if (mark[t[i]]){
        int x=mark[t[i]];
        for (int j=1;j<=cur;j++){
             if (j!=x){
                 pre[x][j]+=cnt[j];
             }
        }
        cnt[x]++;
    }

    if (!keep){
        for (int j=sta[i];j<=fin[i];j++){
             int x=rev[j];
             if (mark[t[x]]){
                  cnt[mark[t[x]]]--;
             }
        }
    }
}

vector <int> pos[25001];
struct BIT{
        int bit[300005];
        vector <int> used;
        void add(int i,int val){

             while (i<=a+4){
                 if (bit[i]==0){
                     used.push_back(i);
                 }
                 bit[i]+=val;
                 i+=i&-i;
             }
        }
        int query(int i){

            int res=0;
            while (i>0){
                 res+=bit[i];
                 i-=i&-i;
            }
            return res;
        }
        void reset(){
            for (auto p:used){
                 bit[p]=0;
            }
            used.clear();
        }
};
BIT f,f1,f2;
bool cmp(pair<int,int> a,pair<int,int> b){
    return sta[a.first]<sta[b.first];
}
int cal(int x,int y){
    vector <pair<int,int>> v;
    f2.reset();
    int res=0;
    for (auto p:pos[x]){
         v.push_back({p,1});
    }
    for (auto p:pos[y]){
         v.push_back({p,2});
    }
    sort(v.begin(),v.end(),cmp);
    for (auto [p1,p2] :v){
         if (p2==1){
             f2.add(fin[p1],1);
         }else{
             res+=f2.query(a)-f2.query(fin[p1]-1);
         }
    }
    return res;
}

signed main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(NULL);
    cout.tie(NULL);
    cin >> a >> b >> c;
    cin >> t[1];
    block=400;
   // block=0;
    sl[t[1]]++;
    pos[t[1]].push_back(1);
    for (int i=2;i<=a;i++){
         int x,y;
         cin >> x >> y;
         z[x].push_back(i);
         t[i]=y;
         pos[t[i]].push_back(i);
         sl[y]++;
    }
    for (int i=1;i<=b;i++){
         if (sl[i]>block){
             cur++;
             mark[i]=cur;
             check[i]=1;
         }
    }
    predfs(1,0);
    dfs(1,0,1);

    // heavy child
    for (int i=1;i<=b;i++){
       if (mark[i]){
         for (auto p:pos[i]){
              f.add(sta[p],1);

         }
         for (int j=1;j<=b;j++){
              if (!mark[j]){
                  for (auto p:pos[j]){
                       cnt1[mark[i]][j]+=f.query(fin[p])-f.query(sta[p]-1);
                  }
              }
         }
         f.reset();
       }
    }
  //  cout << pos[1][0] << " ";
    //heavy par
    for (int i=1;i<=b;i++){
        if (mark[i]){
            for (auto p:pos[i]){
              f1.add(sta[p],1);
              f1.add(fin[p]+1,-1);
            }
            for (int j=1;j<=b;j++){
              if (!mark[j]){
                  for (auto p:pos[j]){
                       cnt2[mark[i]][j]+=f1.query(sta[p]);
                  }
              }
            }
           f1.reset();
        }
    }

    while (c--){
         int x,y;
         cin >> x >> y;
         if (mark[x] && mark[y]){
             cout << pre[x][y] << "\n";
             cout << flush;
         }else if (mark[x] || mark[y]){
             if (mark[x]){
                 cout << cnt2[mark[x]][y]  << "\n";
                 cout << flush;
             }else{
                 cout << cnt1[mark[y]][x]  << "\n";
                 cout << flush;
             }
         }else{
             cout << cal(x,y)  << "\n";
             cout << flush;
         }
    }
    return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...