Submission #244138

# Submission time Handle Problem Language Result Execution time Memory
244138 2020-07-02T16:25:18 Z rqi Synchronization (JOI13_synchronization) C++14
30 / 100
8000 ms 83124 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
    
    map<int, int> 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>();
        map<int, int> m1 = map<int, int>();
        set<pi> s2 = set<pi>();
        swap(listinds[node], l1);
        swap(totop[node], m1);
        swap(fromtop[node], s2);

        // listinds[node].clear();
        // totop[node].clear();
        // fromtop[node].clear();
    }

    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]){
            totop[node][1]+=1;
        }

        for(auto u: dadj[node]){
            if(u.f == prv) continue;
            if(intree[u.f] == 0) continue;

            genToTop(u.f, node);

            map<int, int> 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.f);
                    newset[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.f);
                    newset[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(r+1);
                    if(it == totop[u.f].end()) break;
                    pi a = *it;
                    if(a.f <= l){
                        totop[u.f].erase(a.f);
                        newset[l]+=a.s;
                    }
                    else break;
                }
            }

            swap(totop[u.f], newset);
            for(auto x: totop[u.f]){
                newset[x.f]+=x.s;
            }

            if(sz(totop[node]) < sz(newset)){
                swap(totop[node], newset);
            }

            for(auto x: newset){
                totop[node][x.f]+=x.s;
            }
        }

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

        totop[R][0]+=0;
        totop[R][M+1]+=0; //padding

        auto it = totop[R].begin();
        while(next(it) != totop[R].end()){
            pi bef = *it;
            it = next(it);
            pi old = *it;
            totop[R][old.f]+=bef.s; //make cumulative sums
        }


        for(auto x: fromtop[R]){
            int tim = x.f;
            if(tim == -5) continue;
            auto it = prev(totop[R].lb(tim+1));
            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 16 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 21632 KB Output is correct
6 Correct 31 ms 21888 KB Output is correct
7 Correct 260 ms 24952 KB Output is correct
8 Correct 259 ms 24952 KB Output is correct
9 Correct 250 ms 24824 KB Output is correct
10 Correct 5950 ms 55132 KB Output is correct
11 Correct 6300 ms 55220 KB Output is correct
12 Correct 4235 ms 76792 KB Output is correct
13 Execution timed out 8047 ms 53128 KB Time limit exceeded
14 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Execution timed out 8037 ms 54260 KB Time limit exceeded
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 17 ms 21504 KB Output is correct
2 Correct 20 ms 21504 KB Output is correct
3 Correct 18 ms 21632 KB Output is correct
4 Correct 18 ms 21632 KB Output is correct
5 Correct 20 ms 21632 KB Output is correct
6 Correct 37 ms 22144 KB Output is correct
7 Correct 302 ms 27000 KB Output is correct
8 Correct 4302 ms 76896 KB Output is correct
9 Correct 4263 ms 77084 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 4312 ms 77036 KB Output is correct
2 Correct 3040 ms 82572 KB Output is correct
3 Correct 3025 ms 83124 KB Output is correct
4 Correct 3146 ms 82692 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 17 ms 21504 KB Output is correct
2 Correct 18 ms 21504 KB Output is correct
3 Correct 19 ms 21504 KB Output is correct
4 Correct 18 ms 21504 KB Output is correct
5 Correct 31 ms 21888 KB Output is correct
6 Correct 292 ms 24916 KB Output is correct
7 Correct 7151 ms 55744 KB Output is correct
8 Correct 4468 ms 76832 KB Output is correct
9 Execution timed out 8042 ms 53220 KB Time limit exceeded
10 Halted 0 ms 0 KB -