Submission #674313

#TimeUsernameProblemLanguageResultExecution timeMemory
674313jeroenodbCats or Dogs (JOI18_catdog)C++17
100 / 100
350 ms24388 KiB
#include "catdog.h"
#include "bits/stdc++.h"
using namespace std;
#define all(x) begin(x),end(x)
template<typename A, typename B> ostream& operator<<(ostream &os, const pair<A, B> &p) { return os << '(' << p.first << ", " << p.second << ')'; }
template<typename T_container, typename T = typename enable_if<!is_same<T_container, string>::value, typename T_container::value_type>::type> ostream& operator<<(ostream &os, const T_container &v) { string sep; for (const T &x : v) os << sep << x, sep = " "; return os; }
#define debug(a) cerr << "(" << #a << ": " << a << ")\n";
typedef long long ll;
typedef vector<int> vi;
typedef vector<vi> vvi;
typedef pair<int,int> pi;
const int mxN = 1e5+1, oo = 1e9;

struct F {
    int mat[2][2] = {{0,1},{1,0}};
    friend F op(const F& u,const F& v) {
        F res = {oo,oo,oo,oo};
        for(int i : {0,1}) for(int j : {0,1}) for(int k : {0,1}) {
            res.mat[i][k] = min(res.mat[i][k], u.mat[i][j]+v.mat[j][k]);
        }
        return res;
    }
    int get() {
        int ans=oo;
        for(int i : {0,1}) for(int j : {0,1}) ans = min(ans,mat[i][j]);
        return ans;
    }
    pair<ll,ll> dp() {
        int x=oo,y=oo;
        for(int i : {0,1}) {
            x = min(x,mat[i][0]);
            y = min(y,mat[i][1]);
        }
        return {x,y};
    }
};
template<class T> struct splaytree {
    // flip
    #define L c[0]
    #define R c[1]
    struct node {
        T val;
        node *c[2] = {NULL,NULL}, *par =NULL;
        bool pathtop=true;
        node(const T& v) : val(v) {}
        node() {}
    };
    static void recalc(node* at) {
        at->val.recalc();
        if(at->L) at->val.recalc(at->L->val,0);
        if(at->R) at->val.recalc(at->R->val,1);
    }
    static void print(node* n) {
        if(n==NULL) return;
        print(n->L);
        cout << n->val << ' ';
        print(n->R);
    }
    static void rotate(node* n) {
        // Precondition: n is not the root, Postcondition: rotates n to the place of its parent
        assert(n and !n->pathtop and n->par);
        node* par = n->par;
        if(!par->pathtop) {
            auto gp = par->par;
            if(gp->L==par) gp->L=n;
            else if(gp->R==par) gp->R=n;
        }
        n->par = par->par;
        bool b= n!=par->L;
        #define l c[b]
        #define r c[b^1]
        par->l = n->r; // Fix right child of current node
        if(n->r) n->r->par = par;
        n->r = par; // Put parent under current node
        #undef l
        #undef r
        par->par = n;
        swap(par->pathtop, n->pathtop);
        recalc(par), recalc(n);
    }
    static void splay(node* n) {
        while(!n->pathtop) {
            if(n->par->pathtop) {
                rotate(n);
            } else {
                auto p = n->par, gp = p->par;
                // Double rotations
                if((p->L==n) == (gp->L==p)) rotate(p);
                else rotate(n);
                rotate(n);
            }
        }
    }
    #undef L
    #undef R
};

struct vertex{
    F mine,sub;
    vertex(){}
    void recalc(const vertex& o,bool rev=false) {
        sub  = rev?op(o.sub,sub):op(sub,o.sub);
    }
    void recalc() {
        sub=mine;
    }
}; 
array<array<ll,2>,2> matSingle[3] = {{0,1,1,0}, {0,oo,1,oo}, {oo,1,oo,0}};
struct linkcut {
    // initially the linkcut tree consists of n disconnected size 1 trees.
    typedef splaytree<vertex> bst;
    typedef bst::node node;
    int n=0;
    node* t=NULL;
    linkcut() {}
    linkcut(int nn) {
        n=nn;
        t = new node[n];
        for(int i=0;i<n;++i) {
            t[i] = node(vertex{});
        }
    }
    void attach(node* at, int sgn=1) {
        auto& f = at->par->val.mine;
        auto [x,y] = at->val.sub.dp();
        f.mat[0][1]+=sgn*min(x+1,y);
        f.mat[1][1]+=sgn*min(x+1,y);
        f.mat[0][0]+=sgn*min(x,y+1);
        f.mat[1][0]+=sgn*min(x,y+1);
    }
    void attach(int i, int sgn=1) {
        attach(t+i,sgn);
    }

    node* expose(int u) {
        node *at = NULL, *par = t+u;
        for(;par; at=par,par = par->par) {
            bst::splay(par);
            if(par->c[1]) {
                attach(par->c[1]);
                par->c[1]->pathtop = true;
                par->c[1] = NULL;
            }
            if(at) {
                attach(at,-1);
                at->pathtop = false;
            }
            par->c[1] = at;
            bst::recalc(par);     
        }
        bst::splay(t+u);
        return t+u;
    }
    void link(int u, int v) { // precondition: u is root of tree
        t[u].par = t+v; // connect with unmarked edge
        attach(u);
    }
    ll calc() {
        auto root = expose(0);
        return root->val.sub.get();
    }
    void update(int i, int old, int nw) {
        expose(i);
        for(int j=0;j<2;++j) for(int k=0;k<2;++k) {
            t[i].val.mine.mat[j][k]+=matSingle[nw][j][k]-matSingle[old][j][k];
        }
        
        bst::recalc(t+i);
    }
};
vvi adj;
linkcut tree;
void dfs(int at, int from) {
    for(int to : adj[at]) if(to!=from) {
        dfs(to,at);
        tree.link(to,at);
    }
}
int n;
vi typ;
void initialize(int N, std::vector<int> A, std::vector<int> B) {
    n=N;
    adj.resize(n);
    for(int i=0;i<n-1;++i) {
      adj[A[i]-1].push_back(B[i]-1);
      adj[B[i]-1].push_back(A[i]-1);
    }
    tree = linkcut(n);
    typ.resize(n);
    dfs(0,0);
}
int update(int v, int a) {
  tree.update(v,typ[v],a);
  typ[v]=a;
  return tree.calc();
}
int cat(int v) {
  return update(v-1,2);
}

int dog(int v) {
  return update(v-1,1);
}

int neighbor(int v) {
  return update(v-1,0);
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...