Submission #244128

# Submission time Handle Problem Language Result Execution time Memory
244128 2020-07-02T15:59:32 Z rqi Synchronization (JOI13_synchronization) C++14
30 / 100
8000 ms 83656 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 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));
        }

        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));
        }

        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);
            switchuseful(i);
            for(auto u: cenchildren[i]){
                switchuseful(u);
                //dbg(i, -1, u);
                upd(i, -1);
                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 17 ms 21504 KB Output is correct
3 Correct 17 ms 21504 KB Output is correct
4 Correct 17 ms 21504 KB Output is correct
5 Correct 18 ms 21504 KB Output is correct
6 Correct 34 ms 21888 KB Output is correct
7 Correct 291 ms 24872 KB Output is correct
8 Correct 271 ms 24824 KB Output is correct
9 Correct 291 ms 24828 KB Output is correct
10 Correct 6569 ms 55008 KB Output is correct
11 Correct 7059 ms 55380 KB Output is correct
12 Correct 4861 ms 77600 KB Output is correct
13 Execution timed out 8032 ms 53284 KB Time limit exceeded
14 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Execution timed out 8055 ms 54772 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 18 ms 21504 KB Output is correct
3 Correct 18 ms 21632 KB Output is correct
4 Correct 20 ms 21632 KB Output is correct
5 Correct 21 ms 21632 KB Output is correct
6 Correct 41 ms 22136 KB Output is correct
7 Correct 333 ms 27000 KB Output is correct
8 Correct 4949 ms 77732 KB Output is correct
9 Correct 4918 ms 77616 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 4933 ms 77820 KB Output is correct
2 Correct 3838 ms 83288 KB Output is correct
3 Correct 3887 ms 83656 KB Output is correct
4 Correct 3979 ms 83552 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 18 ms 21504 KB Output is correct
2 Correct 19 ms 21504 KB Output is correct
3 Correct 17 ms 21504 KB Output is correct
4 Correct 18 ms 21504 KB Output is correct
5 Correct 34 ms 21888 KB Output is correct
6 Correct 291 ms 25044 KB Output is correct
7 Correct 7750 ms 55784 KB Output is correct
8 Correct 5099 ms 77996 KB Output is correct
9 Execution timed out 8042 ms 53092 KB Time limit exceeded
10 Halted 0 ms 0 KB -