Submission #1276766

#TimeUsernameProblemLanguageResultExecution timeMemory
1276766uzukishinobuWerewolf (IOI18_werewolf)C++20
100 / 100
457 ms98660 KiB
#include "werewolf.h"
#include <bits/stdc++.h>
using namespace std;

const int MAXA = 1000005;
const int MAXV = 400005;
int a,b;
pair<int,int> edge[MAXA];
vector<int> z[MAXV][2];
bool cmp(pair<int,int> A,pair<int,int> B){
     return max(A.first,A.second) < max(B.first,B.second);
}
bool cmp1(pair<int,int> A,pair<int,int> B){
     return min(A.first,A.second) > min(B.first,B.second);
}

int root1, root2;
int rev[MAXV][2];
struct dsu{
      int par[MAXV];
      int root;
      void init(int n){
          for (int i=1;i<=n;i++) par[i]=i;
          root = 0;
      }
      int find(int u){
          if (par[u]==u) return u;
          return par[u]=find(par[u]);
      }
      void join(int x,int y,int t){
          x=find(x);
          y=find(y);
          if (x==y) return;
          z[x][t].push_back(y);
          root = x;
          par[y]=x;
      }
};
dsu d;

int parA[MAXV][21][2];
int sta[MAXV][2];
int finA[MAXV][2];
int tour;

void dfs(int i,int t){
    if (i==0) return;
    tour++;
    sta[i][t]=tour;
    rev[tour][t]=i;
    for (auto p: z[i][t]){
         parA[p][0][t]=i;
         dfs(p,t);
    }
    finA[i][t]=tour;
}

struct node{
     int l,r,base,id;
};
vector<node> pos[MAXV];
int resArr[MAXV];
int bit[MAXV];

void update(int i,int val){
    while (i < MAXV){
         bit[i] += val;
         i += i & -i;
    }
}
int query(int i){
    int res=0;
    while (i>0){
         res += bit[i];
         i -= i & -i;
    }
    return res;
}

vector<int> ans;

vector<int> check_validity(int N, vector<int> X, vector<int> Y,vector<int> S, vector<int> E,vector<int> L, vector<int> R) {
    int q = (int)L.size();
    ans.assign(q, 0);
    a = N;
    b = (int)X.size();

    for (int i=0;i<=a+5 && i<MAXV;i++){
        z[i][0].clear();
        z[i][1].clear();
        pos[i].clear();
        resArr[i]=0;
        sta[i][0]=sta[i][1]=0;
        finA[i][0]=finA[i][1]=0;
        for (int j=0;j<21;j++){
            parA[i][j][0]=parA[i][j][1]=0;
        }
        rev[i][0]=rev[i][1]=0;
        bit[i]=0;
    }

    for (int i=0;i<b;i++){
         X[i]++; Y[i]++;
    }
    for (int i=0;i<q;i++){
         L[i]++; R[i]++; S[i]++; E[i]++;
    }
    for (int i=0;i<b;i++){
         edge[i] = {X[i], Y[i]};
    }

    sort(edge, edge + b, cmp);
    d.init(a);
    for (int i=0;i<b;i++){
         int u = max(edge[i].first, edge[i].second);
         int v = min(edge[i].first, edge[i].second);
         d.join(u, v, 0);
    }
    root1 = d.root;
    sort(edge, edge + b, cmp1);
    d.init(a);
    for (int i=0;i<b;i++){
         int u = min(edge[i].first, edge[i].second);
         int v = max(edge[i].first, edge[i].second);
         d.join(u, v, 1);
    }
    root2 = d.root;

    tour = 0;
    if (root2 != 0) dfs(root2, 1);
    tour = 0;
    if (root1 != 0) dfs(root1, 0);

    for (int j=1;j<=20;j++){
         for (int i=1;i<=a;i++){
              int up0 = parA[i][j-1][0];
              int up1 = parA[i][j-1][1];
              parA[i][j][0] = (up0>0 ? parA[up0][j-1][0] : 0);
              parA[i][j][1] = (up1>0 ? parA[up1][j-1][1] : 0);
         }
    }

    for (int i=0;i<q;i++){
         int x = S[i];
         int y = E[i];
         int l = L[i];
         int r = R[i];
         for (int j=20;j>=0;j--){
              if (parA[x][j][1] >= l && parA[x][j][1] != 0) x = parA[x][j][1];
              if (parA[y][j][0] != 0 && parA[y][j][0] <= r) y = parA[y][j][0];
         }
         if (sta[x][1] == 0 || sta[y][0] == 0) continue;
         pos[sta[x][1]-1].push_back({sta[y][0], finA[y][0], -1, i});
         pos[finA[x][1]].push_back({sta[y][0], finA[y][0], 1, i});
    }

    int maxTour1 = 0;
    for (int i=1;i<=a;i++) if (sta[i][1] > maxTour1) maxTour1 = sta[i][1];

    for (int i=0;i<=maxTour1;i++){
         if (rev[i][1] != 0 && sta[rev[i][1]][0] != 0){
             update(sta[rev[i][1]][0], 1);
         }
         for (auto &p: pos[i]){
              int add = query(p.r) - query(p.l - 1);
              resArr[p.id] += p.base * add;
         }
    }

    for (int i=0;i<q;i++){
         ans[i] = (resArr[i] > 0);
    }
    return ans;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...