Submission #244189

# Submission time Handle Problem Language Result Execution time Memory
244189 2020-07-02T18:18:30 Z rqi Synchronization (JOI13_synchronization) C++14
30 / 100
8000 ms 83680 KB
#include <bits/stdc++.h>
using namespace std;
 
typedef long long ll;
typedef long double ld;
typedef double db; 
typedef string str; 
 
typedef pair<int,int> pi;
typedef pair<ll,ll> pl; 
typedef pair<db,db> pd; 
 
typedef vector<int> vi; 
typedef vector<ll> vl; 
typedef vector<db> vd; 
typedef vector<str> vs; 
typedef vector<pi> vpi;
typedef vector<pl> vpl; 
typedef vector<pd> vpd; 
 
#define mp make_pair
#define f first
#define s second
#define sz(x) (int)x.size()
#define all(x) begin(x), end(x)
#define rall(x) (x).rbegin(), (x).rend() 
#define rsz resize
#define ins insert 
#define ft front() 
#define bk back()
#define pf push_front 
#define pb push_back
#define eb emplace_back 
#define lb lower_bound 
#define ub upper_bound 
 
#define FOR(i,a,b) for (int i = (a); i < (b); ++i)
#define F0R(i,a) FOR(i,0,a)
#define ROF(i,a,b) for (int i = (b)-1; i >= (a); --i)
#define R0F(i,a) ROF(i,0,a)
#define trav(a,x) for (auto& a: x)
 
const int MOD = 1e9+7; // 998244353;
const int MX = 2e5+5; 
const ll INF = 1e18; 
const ld PI = acos((ld)-1);
const int xd[4] = {1,0,-1,0}, yd[4] = {0,1,0,-1}; 
mt19937 rng((uint32_t)chrono::steady_clock::now().time_since_epoch().count()); 
 
template<class T> bool ckmin(T& a, const T& b) { 
    return b < a ? a = b, 1 : 0; }
template<class T> bool ckmax(T& a, const T& b) { 
    return a < b ? a = b, 1 : 0; } 
int pct(int x) { return __builtin_popcount(x); } 
int bits(int x) { return 31-__builtin_clz(x); } // floor(log2(x)) 
int cdiv(int a, int b) { return a/b+!(a<0||a%b == 0); } // division of a by b rounded up, assumes b > 0 
int fstTrue(function<bool(int)> f, int lo, int hi) {
    hi ++; assert(lo <= hi); // assuming f is increasing
    while (lo < hi) { // find first index such that f is true 
        int mid = (lo+hi)/2; 
        f(mid) ? hi = mid : lo = mid+1; 
    } 
    return lo;
}
 
// INPUT
template<class A> void re(complex<A>& c);
template<class A, class B> void re(pair<A,B>& p);
template<class A> void re(vector<A>& v);
template<class A, size_t SZ> void re(array<A,SZ>& a);
 
template<class T> void re(T& x) { cin >> x; }
void re(db& d) { str t; re(t); d = stod(t); }
void re(ld& d) { str t; re(t); d = stold(t); }
template<class H, class... T> void re(H& h, T&... t) { re(h); re(t...); }
 
template<class A> void re(complex<A>& c) { A a,b; re(a,b); c = {a,b}; }
template<class A, class B> void re(pair<A,B>& p) { re(p.f,p.s); }
template<class A> void re(vector<A>& x) { trav(a,x) re(a); }
template<class A, size_t SZ> void re(array<A,SZ>& x) { trav(a,x) re(a); }
 
// TO_STRING
#define ts to_string
str ts(char c) { return str(1,c); }
str ts(bool b) { return b ? "true" : "false"; }
str ts(const char* s) { return (str)s; }
str ts(str s) { return s; }
template<class A> str ts(complex<A> c) { 
    stringstream ss; ss << c; return ss.str(); }
str ts(vector<bool> v) { 
    str res = "{"; F0R(i,sz(v)) res += char('0'+v[i]);
    res += "}"; return res; }
template<size_t SZ> str ts(bitset<SZ> b) {
    str res = ""; F0R(i,SZ) res += char('0'+b[i]);
    return res; }
template<class A, class B> str ts(pair<A,B> p);
template<class T> str ts(T v) { // containers with begin(), end()
    bool fst = 1; str res = "{";
    for (const auto& x: v) {
        if (!fst) res += ", ";
        fst = 0; res += ts(x);
    }
    res += "}"; return res;
}
template<class A, class B> str ts(pair<A,B> p) {
    return "("+ts(p.f)+", "+ts(p.s)+")"; }
 
// OUTPUT
template<class A> void pr(A x) { cout << ts(x); }
template<class H, class... T> void pr(const H& h, const T&... t) { 
    pr(h); pr(t...); }
void ps() { pr("\n"); } // print w/ spaces
template<class H, class... T> void ps(const H& h, const T&... t) { 
    pr(h); if (sizeof...(t)) pr(" "); ps(t...); }
 
// DEBUG
void DBG() { cerr << "]" << endl; }
template<class H, class... T> void DBG(H h, T... t) {
    cerr << ts(h); if (sizeof...(t)) cerr << ", ";
    DBG(t...); }
#ifdef LOCAL // compile with -DLOCAL
#define dbg(...) cerr << "LINE(" << __LINE__ << ") -> [" << #__VA_ARGS__ << "]: [", DBG(__VA_ARGS__)
#else
#define dbg(...) 0
#endif
 
// FILE I/O
void setIn(string s) { freopen(s.c_str(),"r",stdin); }
void setOut(string s) { freopen(s.c_str(),"w",stdout); }
void unsyncIO() { ios_base::sync_with_stdio(0); cin.tie(0); }
void setIO(string s = "") {
    unsyncIO();
    // cin.exceptions(cin.failbit); 
    // throws exception when do smth illegal
    // ex. try to read letter into int
    if (sz(s)) { setIn(s+".in"), setOut(s+".out"); } // for USACO
}
 
const int mx = 100005;
int N, M, Q;
int ans[mx];
//#warning overflow in ans?
vi change[mx];
 
/**
 * Description: The centroid of a tree of size $N$ is a vertex such that 
     * after removing it, all resulting subtrees have size at most $\frac{N}{2}.$ 
     * Supports updates in the form ``add 1 to all verts $v$ such that $dist(x,v)\le y$."
 * Time: O(N\log N) build, O(\log N) update and query
 * Memory: O(N\log N)
 * Source: own
 * Verification: 
    * solves https://dmoj.ca/problem/dmopc19c7p6
    * https://codeforces.com/contest/342/problem/E
    * Triway Cup 2019 G
 */
 
template<int SZ> struct Centroid {
    vi adj[SZ]; 
    vpi dadj[SZ]; //node, edge number
    void ae(int a,int b, int c){
        adj[a].pb(b),adj[b].pb(a);
        dadj[a].pb(mp(b, c)); dadj[b].pb(mp(a, c));
    }
    
    bool done[SZ]; // processed as centroid yet
    int N,sub[SZ],cen[SZ],lev[SZ]; // subtree size, centroid anc
    vi cenchildren[SZ]; // centroid children
    int dist[32-__builtin_clz(SZ)][SZ]; // dists to all ancs
 
    void dfs(int x, int p) { sub[x] = 1; 
        trav(y,adj[x]) if (!done[y] && y != p) 
            dfs(y,x), sub[x] += sub[y]; 
    }
    int centroid(int x) {
        dfs(x,-1); 
        for (int sz = sub[x];;) {
            pi mx = {0,0};
            trav(y,adj[x]) if (!done[y] && sub[y] < sub[x]) 
                ckmax(mx,{sub[y],y});
            if (mx.f*2 <= sz) return x; 
            x = mx.s;
        }
    }
    void genDist(int x, int p, int lev) {
        dist[lev][x] = dist[lev][p]+1;
        trav(y,adj[x]) if (!done[y] && y != p) genDist(y,x,lev); }
    void gen(int CEN, int _x) { // CEN = centroid above x
        int x = centroid(_x); done[x] = 1; cen[x] = CEN; 
        sub[x] = sub[_x]; lev[x] = (CEN == -1 ? 0 : lev[CEN]+1);
        dist[lev[x]][x] = 0; 
        trav(y,adj[x]) if (!done[y]) genDist(y,x,lev[x]);
        trav(y,adj[x]) if (!done[y]) gen(x,y);
    }
    void init(int _N) { N = _N; FOR(i,1,N+1) done[i] = 0;
        gen(-1,1); 
        for(int i = 1; i <= N; i++){
            if(cen[i] == -1) continue;
            cenchildren[cen[i]].pb(i);
        }
    } // start at vert 1
 
    bool intree[SZ]; //inside of the current tree. 
    bool useful[SZ]; //considering these nodes, some won't be considered when subtracting
    list<int> listinds[SZ]; //corresponding nodes for each index
    
    set<pi> totop[SZ]; //time, # of nodes for that time
    set<pi> fromtop[SZ]; //time, index of list for that time
 
    //#warning Clear out all memory in between upds
    //#warning remember to continue out of notintree nodes, only consider useful nodes
    
    void clearDataNode(int node){//DO NOT CLEAR INTREE OR USEFUL
        list<int> l1 = list<int>();
        set<pi> s1 = set<pi>();
        set<pi> s2 = set<pi>();
        swap(listinds[node], l1);
        swap(totop[node], s1);
        swap(fromtop[node], s2);
    
        // listinds[node].clear();
        // totop[node].clear();
        // fromtop[node].clear();
    }
    void clearData(int node, int prv = -1){//DO NOT CLEAR INTREE OR USEFUL
        for(auto u: adj[node]){
            if(u == prv) continue;
            if(intree[u] == 0) continue;
            clearData(u, node);
        }
        list<int> l1 = list<int>();
        set<pi> s1 = set<pi>();
        set<pi> s2 = set<pi>();
        swap(listinds[node], l1);
        swap(totop[node], s1);
        swap(fromtop[node], s2);
 
        // listinds[node].clear();
        // totop[node].clear();
        // fromtop[node].clear();
    }
 
    void setad(set<pi> &a, pi b){
        auto it = a.lb(mp(b.f, 0)); //is there a pair with time l?
        if(it != a.end() && it->f == b.f){
            pi x = *it; //combine a with x
            a.erase(x);
            a.ins(mp(b.f, x.s+b.s));
        }
        else{
            a.ins(b);
        }
    }
 
    void setlistad(set<pi> &a, pi b){
 
        auto it = a.lb(mp(b.f, 0)); //is there a pair with time l?
        if(it != a.end() && it->f == b.f){
            pi x = *it; //combine a with x
            a.erase(x);
            listinds[b.s].splice(listinds[b.s].begin(), listinds[x.s]);
            a.ins(b);
        }
        else{
            a.ins(b);
        }
    }
 
 
    void genToTop(int node, int prv = -1){
        //dbg("M6");
        if(useful[node]){
            setad(totop[node], mp(1, 1));
        }
        else if(prv != -1) return;
 
        for(auto u: dadj[node]){
            if(u.f == prv) continue;
            if(intree[u.f] == 0) continue;
 
            genToTop(u.f, node);
 
            set<pi> newset; //transform totop[u.f] into this
 
            while(true){
                if(sz(totop[u.f]) == 0) break;
                int L = M+5;
                if(sz(change[u.s]) > 0){
                    L = change[u.s][0];
                }
                auto it = totop[u.f].begin();
                pi a = *it;
                if(a.f <= L){
                    totop[u.f].erase(a);
                    setad(newset, mp(L, a.s));
                }
                else break;
            }
 
            while(true){
                if(sz(totop[u.f]) == 0) break;
 
                assert(sz(change[u.s]) > 0);
 
                auto it = prev(totop[u.f].end());
                pi a = *it;
                if(a.f > change[u.s].back()){
                    totop[u.f].erase(a);
                    setad(newset, mp(M+5, a.s));
                }
                else break;
            }
 
            for(int i = 1; i < sz(change[u.s])-1; i+=2){
                int r = change[u.s][i];
                int l = change[u.s][i+1];
                while(true){
                    if(sz(totop[u.f]) == 0) break;
 
                    auto it = totop[u.f].lb(mp(r+1, -10));
                    if(it == totop[u.f].end()) break;
                    pi a = *it;
                    if(a.f <= l){
                        totop[u.f].erase(a);
                        setad(newset, mp(l, a.s));
                    }
                    else break;
                }
            }
 
            swap(totop[u.f], newset);
            for(auto x: totop[u.f]){
                setad(newset, x);
            }
 
            if(sz(totop[node]) < sz(newset)){
                swap(totop[node], newset);
            }
 
            for(auto x: newset){
                setad(totop[node], x);
            }
        }
 
        // dbg(node);
        // dbg(totop[node]);
 
    }
 
    void genFromTop(int node, int prv = -1){
        //dbg("M5");
        if(useful[node]){
            listinds[node].pb(node);
            setlistad(fromtop[node], mp(M+1, node));
        }
        else if(prv != -1) return;
 
        for(auto u: dadj[node]){
            if(u.f == prv) continue;
            if(intree[u.f] == 0) continue;
 
            genFromTop(u.f, node);
 
            set<pi> newset; //transform fromtop[u.f] into this
            if(sz(fromtop[u.f]) == 0) continue;
 
            while(true){
                if(sz(fromtop[u.f]) == 0) break;
                auto it = prev(fromtop[u.f].end());
                pi a = *it;
                int R = -5;
                if(sz(change[u.s])){
                    R = change[u.s].back();
                }
                if(R <= a.f){
                    fromtop[u.f].erase(a);
                    setlistad(newset, mp(R, a.s));
                }
                else break;
            }
 
            while(true){
                if(sz(fromtop[u.f]) == 0) break;
                auto it = fromtop[u.f].begin();
                pi a = *it;
                assert(sz(change[u.s]) > 0);
                if(a.f < change[u.s][0]){
                    fromtop[u.f].erase(a);
                    setlistad(newset, mp(-5, a.s));
                }
                else break;
            }
 
            for(int i = 1; i < sz(change[u.s])-1; i+=2){
                int r = change[u.s][i];
                int l = change[u.s][i+1];
                while(true){
                    if(sz(fromtop[u.f]) == 0) break;
                    auto it = fromtop[u.f].lb(mp(r, -10));
                    if(it == fromtop[u.f].end()) break;
                    pi a = *it;
                    if(a.f < l){
                        fromtop[u.f].erase(a);
                        setlistad(newset, mp(r, a.s));
                    }
                    else break;
                }
            }
            swap(fromtop[u.f], newset);
            //fromtop contains all changed elements now
            for(auto &x: fromtop[u.f]){
                setlistad(newset, x);
            }
            //newset has everything
            if(sz(fromtop[node]) < sz(newset)){
                swap(fromtop[node], newset);
            }
            for(auto &x: newset){
                setlistad(fromtop[node], x);
            }
 
            ///////////////////
 
        }
 
        // dbg(node);
        // for(auto u: fromtop[node]){
        //     dbg(u, listinds[u.s]);
        // }
    }
 
    void upd(int R, int mode){ //centroid top node, mode = 1 if adding, -1 if subtracting
        //dbg("M4");
        genToTop(R); //upds stored in totop[R]
        genFromTop(R);
 
        // dbg(totop[R]);
        // for(auto u: fromtop[R]){
        //     dbg(u, listinds[u.s]);
        // }
 
        setad(totop[R], mp(0, 0)); //padding
        setad(totop[R], mp(M+1, 0));
 
        auto it = totop[R].begin();
        while(next(it) != totop[R].end()){
            pi bef = *it;
            it = next(it);
            pi old = *it;
            totop[R].erase(old);
            totop[R].ins(mp(old.f, old.s+bef.s)); //make cumulative sums
            it = totop[R].find(mp(old.f, old.s+bef.s));
        }
 
 
        for(auto x: fromtop[R]){
            int tim = x.f;
            if(tim == -5) continue;
            auto it = prev(totop[R].lb(mp(tim+1, 0)));
            int val = it->s;
            for(auto u: listinds[x.s]){
                //dbg(R, u, val, mode);
                ans[u]+=val*mode;
            }
        }
 
 
        clearData(R);
    }
 
    void switchintree(int node){ //switches intree values in centroid subtree 
        //dbg("M3");
        intree[node]^=1;
        for(auto u: cenchildren[node]){
            switchintree(u);
        }
    }
 
    void switchuseful(int node){
        //dbg("M2");
        useful[node]^=1;
        for(auto u: cenchildren[node]){
            switchuseful(u);
        }
    }
 
    void solve(){ //goal is to update ans[]
        //dbg("M1");
        for(int i = 1; i <= N; i++){
            switchintree(i);
            switchuseful(i);
            //dbg(i, 1);
            upd(i, 1);
            clearData(i);
            switchuseful(i);
            for(auto u: cenchildren[i]){
                switchuseful(u);
                //dbg(i, -1, u);
                upd(i, -1);
                clearData(u);
                clearDataNode(i);
                switchuseful(u);
            }
            switchintree(i);
        }
    }
 
};
 
Centroid<mx> cent;
 
int main() {
    setIO();
    cin >> N >> M >> Q;
    for(int i = 1; i <= N-1; i++){
        int X, Y;
        cin >> X >> Y;
        cent.ae(X, Y, i);
    }
    for(int i = 1; i <= M; i++){
        int D;
        cin >> D;
        change[D].pb(i);
    }
    for(int i = 1; i <= N-1; i++){
        if(sz(change[i]) % 2 == 1){
            change[i].pb(M);
        }
    }
 
    cent.init(N);
 
    // for(int i = 1; i <= N; i++){
    //     dbg(i, cent.cen[i]);
    // }
 
    cent.solve();
 
    for(int i = 1; i <= Q; i++){
        int C;
        cin >> C;
        ps(ans[C]);
    }
 
    // you should actually read the stuff at the bottom
}
 
/* stuff you should look for
    * int overflow, array bounds
    * special cases (n=1?)
    * do smth instead of nothing and stay organized
    * WRITE STUFF DOWN
*/
 

Compilation message

synchronization.cpp: In function 'void setIn(std::__cxx11::string)':
synchronization.cpp:128:31: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)', declared with attribute warn_unused_result [-Wunused-result]
 void setIn(string s) { freopen(s.c_str(),"r",stdin); }
                        ~~~~~~~^~~~~~~~~~~~~~~~~~~~~
synchronization.cpp: In function 'void setOut(std::__cxx11::string)':
synchronization.cpp:129:32: warning: ignoring return value of 'FILE* freopen(const char*, const char*, FILE*)', declared with attribute warn_unused_result [-Wunused-result]
 void setOut(string s) { freopen(s.c_str(),"w",stdout); }
                         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
# Verdict Execution time Memory Grader output
1 Correct 18 ms 21504 KB Output is correct
2 Correct 16 ms 21504 KB Output is correct
3 Correct 16 ms 21504 KB Output is correct
4 Correct 16 ms 21504 KB Output is correct
5 Correct 17 ms 21632 KB Output is correct
6 Correct 32 ms 21888 KB Output is correct
7 Correct 262 ms 24952 KB Output is correct
8 Correct 267 ms 24824 KB Output is correct
9 Correct 277 ms 24824 KB Output is correct
10 Correct 5791 ms 55060 KB Output is correct
11 Correct 6413 ms 55160 KB Output is correct
12 Correct 4833 ms 77536 KB Output is correct
13 Execution timed out 8077 ms 53284 KB Time limit exceeded
14 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Execution timed out 8041 ms 54672 KB Time limit exceeded
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 18 ms 21504 KB Output is correct
2 Correct 17 ms 21504 KB Output is correct
3 Correct 17 ms 21632 KB Output is correct
4 Correct 18 ms 21632 KB Output is correct
5 Correct 19 ms 21632 KB Output is correct
6 Correct 39 ms 22016 KB Output is correct
7 Correct 347 ms 27196 KB Output is correct
8 Correct 4784 ms 77688 KB Output is correct
9 Correct 4854 ms 77732 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 4908 ms 77944 KB Output is correct
2 Correct 3779 ms 83324 KB Output is correct
3 Correct 3929 ms 83540 KB Output is correct
4 Correct 3894 ms 83680 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 18 ms 21504 KB Output is correct
2 Correct 16 ms 21504 KB Output is correct
3 Correct 16 ms 21504 KB Output is correct
4 Correct 17 ms 21632 KB Output is correct
5 Correct 34 ms 21888 KB Output is correct
6 Correct 268 ms 24952 KB Output is correct
7 Correct 6959 ms 55612 KB Output is correct
8 Correct 5178 ms 77748 KB Output is correct
9 Execution timed out 8055 ms 53092 KB Time limit exceeded
10 Halted 0 ms 0 KB -