Submission #1147384

#TimeUsernameProblemLanguageResultExecution timeMemory
1147384sonamooCats or Dogs (JOI18_catdog)C++20
100 / 100
434 ms28740 KiB
#include "catdog.h" #include <bits/stdc++.h> #define pii pair<int,int> #define ll long long int #define SIZE 100005 #define all(v) v.begin(), v.end() #define pb push_back #define MOD 1000000007 #define INF 1000000007 using namespace std; int n; vector<int> g[SIZE] , child[SIZE]; int C[SIZE]; int sz[SIZE] , dep[SIZE] , pa[SIZE]; int num[SIZE] , TOP[SIZE] , BOT[SIZE]; int L[SIZE][2]; struct ST{ struct Node { int v[2][2] , e; int getmin() const { return min(min(v[0][0] , v[0][1]) , min(v[1][0] , v[1][1])); } Node operator+(const Node& b) { if (e==1) return b; if (b.e==1) return {v[0][0] , v[0][1] , v[1][0] , v[1][1] , e}; Node val={INF , INF , INF , INF , 0}; for (int i = 0; i < 2; i++) for (int j = 0; j < 2; j++) for (int k = 0; k < 2; k++) for (int l = 0; l < 2; l++) val.v[i][l] = min(val.v[i][l] , v[i][j]+b.v[k][l]+(j!=k)); return val; } }; Node tree[SIZE*4]; //build void build(int nod , int nl , int nr) { if (nl == nr) { tree[nod] = {0 , INF , INF , 0 , 0}; return; } int m = (nl+nr)/2; build(nod*2 , nl , m); build(nod*2+1 , m+1 , nr); tree[nod] = tree[nod*2]+tree[nod*2+1]; } //query Node query(int nod , int nl , int nr , int l , int r) { if (nr < l || r < nl) return {INF , INF , INF , INF , 1}; if (l <= nl && nr <= r) return tree[nod]; int m = (nl+nr)/2; Node Lval = query(nod*2 , nl , m , l , r); Node Rval = query(nod*2+1 , m+1 , nr , l , r); return Lval+Rval; } //update void update(int nod , int nl , int nr , int idx , Node val) { if (nr < idx || idx < nl) return; if (nl == nr) { tree[nod]=val; return; } int m = (nl+nr)/2; update(nod*2 , nl , m , idx , val); update(nod*2+1 , m+1 , nr , idx , val); tree[nod] = tree[nod*2]+tree[nod*2+1]; } pii G(Node X) { return {min(X.v[0][0] , X.v[0][1]) , min(X.v[1][0] , X.v[1][1])}; } void upd(int idx) { Node ret = {INF , INF , INF , INF , 0}; if (C[idx]!=2) ret.v[0][0] = L[idx][0]; if (C[idx]!=1) ret.v[1][1] = L[idx][1]; update(1 , 1 , n , idx , ret); } }seg; void bui(int here , int p) { for (auto t : g[here]) { if (p == t) continue; pa[t] = here; dep[t] = dep[here]+1; child[here].pb(t); bui(t , here); } } void getsz(int here) { sz[here]=1; for (auto &t : child[here]) { getsz(t); sz[here] += sz[t]; if (sz[t] > sz[child[here].front()]) swap(child[here].front() , t); } } int pv; void hld(int here) { num[here] = ++pv; bool isFirst=true; for (auto t : child[here]) { if (isFirst) { TOP[t] = TOP[here]; isFirst=false; } else TOP[t]=t; hld(t); } BOT[here] = child[here].size() > 0 ? BOT[child[here][0]] : here; } int solve(int idx , int x) { C[num[idx]] = x; while(TOP[idx]!=1) { auto [prv0 , prv1] = seg.G(seg.query(1 , 1 , n , num[TOP[idx]] , num[BOT[idx]])); seg.upd(num[idx]); auto [cur0 , cur1] = seg.G(seg.query(1 , 1 , n , num[TOP[idx]] , num[BOT[idx]])); idx = pa[TOP[idx]]; L[num[idx]][0] += min(cur0 , cur1+1)-min(prv0 , prv1+1); L[num[idx]][1] += min(cur0+1 , cur1)-min(prv0+1 , prv1); } seg.upd(num[idx]); return seg.query(1 , 1 , n , num[TOP[idx]] , num[BOT[idx]]).getmin(); } void initialize(int N, std::vector<int> A, std::vector<int> B) { n = N; for (int i = 0; i < A.size(); i++) { g[A[i]].pb(B[i]); g[B[i]].pb(A[i]); } bui(1,-1); getsz(1); TOP[1]=1; hld(1); seg.build(1 , 1 , n); } int cat(int v) { return solve(v , 1); } int dog(int v) { return solve(v , 2); } int neighbor(int v) { return solve(v , 3); }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...