Submission #1347106

#TimeUsernameProblemLanguageResultExecution timeMemory
1347106Newtonabc늑대인간 (IOI18_werewolf)C++20
100 / 100
1209 ms295096 KiB
#include "werewolf.h"
#include<bits/stdc++.h>
using namespace std;
const int M=6e5+10;
const int K=1<<19;
struct KRT{
    vector<vector<int>> adj,d;
    vector<int> pa,dep,ag,lb,rb,rev,wi;
    int cnt,ti;
    void init(int n){
        pa.resize(M);
        for(int i=1;i<=n;i++) pa[i]=i;
        cnt=n;
        adj.resize(M);
        dep.resize(M,0);
        ag.resize(M,0);
        d.resize(M,vector<int>(20,0));
        lb.resize(M),rb.resize(M),rev.resize(M),wi.resize(M);
    }
    int root(int x){if(pa[x]==x) return x; return pa[x]=root(pa[x]);}
    void add(int u,int v,int w){
        int ru=root(u),rv=root(v);
        cnt++;
        pa[cnt]=pa[ru]=pa[rv]=cnt;
        wi[cnt]=w;
        adj[cnt].push_back(ru);
        if(ru!=rv) adj[cnt].push_back(rv);
        d[ru][0]=d[rv][0]=cnt;
    }
    void dfs(int u,int p){
        int c=0;
        lb[u]=INT_MAX,rb[u]=INT_MIN;
        for(auto v:adj[u]){
            if(v==p) continue;
            dep[v]=dep[u]+1;
            dfs(v,u);
            lb[u]=min(lb[u],lb[v]);
            rb[u]=max(rb[u],rb[v]);
            c++;
        }
        if(c==0) ag[u]=++ti,lb[u]=rb[u]=ti,rev[ti]=u;
    }
    void initlca(){
        d[cnt][0]=cnt;
        for(int i=1;i<=19;i++){
            for(int j=1;j<=cnt;j++) d[j][i]=d[d[j][i-1]][i-1];
        }
        dfs(cnt,cnt);
    }
    //find upmost such that still able to traverse in weight (L,N) for human
    int fd(int x,int st){
        for(int i=19;i>=0;i--) if(wi[d[st][i]]>=x) st=d[st][i];
        return st;
    }
    //find upmost such that still able to traverse in weight (1,R) for wolf
    int fdb(int x,int st){
        for(int i=19;i>=0;i--) if(wi[d[st][i]]<=x) st=d[st][i];
        return st;
    }

}wf,hm;
struct UWU{
    vector<vector<int>> s;
    vector<int> arr;
    void init(){
        s.resize(K);
        arr.resize(K);
    }
    void build(int l,int r,int idx){
        if(l==r){
            s[idx].push_back(arr[l]);
            return;
        }
        int ia=0,ib=0;
        int m=(l+r)/2;
        build(l,m,idx*2);
        build(m+1,r,idx*2+1);
        while(ia<s[idx*2].size() && ib<s[idx*2+1].size()){
            if(s[idx*2][ia]<=s[idx*2+1][ib]) s[idx].push_back(s[idx*2][ia++]);
            else s[idx].push_back(s[idx*2+1][ib++]);
        }
        while(ia<s[idx*2].size()) s[idx].push_back(s[idx*2][ia++]);
        while(ib<s[idx*2+1].size()) s[idx].push_back(s[idx*2+1][ib++]);
    }
    //find minimal value in range arr[l]...arr[r] which >=val
    int query(int l,int r,int idx,int a,int b,int val){
        if(a>r || b<l) return INT_MAX;
        if(a<=l && b>=r){
            auto it=lower_bound(s[idx].begin(),s[idx].end(),val);
            if(it==s[idx].end()) return INT_MAX;
            return *it;
        }
        int m=(l+r)/2;
        return min(query(l,m,idx*2,a,b,val),query(m+1,r,idx*2+1,a,b,val));
    }
}treee;
std::vector<int> check_validity(int N,vector<int> X, vector<int> Y,vector<int> S,vector<int> E,
        vector<int> L, std::vector<int> R) {
    vector<int> ret(S.size());
    int m=X.size(),q=S.size();
    hm.init(N),wf.init(N);
    treee.init();
    vector<tuple<int,int,int>> edge;
    //make KRT for human route
    for(int i=0;i<m;i++){
        X[i]++,Y[i]++;
        edge.push_back({min(X[i],Y[i]),X[i],Y[i]});
    }
    sort(edge.begin(),edge.end(),greater<tuple<int,int,int>>());
    for(auto [w,u,v]:edge) hm.add(u,v,w);
    hm.initlca();
    //wolffff
    edge.clear();
    for(int i=0;i<m;i++){
        edge.push_back({max(X[i],Y[i]),X[i],Y[i]});
    }
    sort(edge.begin(),edge.end());
    for(auto [w,u,v]:edge) wf.add(u,v,w);
    wf.initlca();
    for(int i=1;i<=N;i++) treee.arr[i]=hm.ag[wf.rev[i]];
    treee.build(1,N,1);
    for(int i=0;i<q;i++){
        S[i]++,E[i]++,L[i]++,R[i]++;
        //node range (lb[lc],rb[lc])(hm index) os able to traverse by human
        int lc=hm.fd(L[i],S[i]);
        int lcw=wf.fdb(R[i],E[i]);
        int mn=treee.query(1,N,1,wf.lb[lcw],wf.rb[lcw],hm.lb[lc]);
        ret[i]=mn<=hm.rb[lc];
    }
    return ret;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...