답안 #244145

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
244145 2020-07-02T16:38:32 Z rqi 동기화 (JOI13_synchronization) C++14
0 / 100
8000 ms 262148 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
    
    map<int, int> totop[SZ]; //time, # of nodes for that time
    map<int, list<int>> 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);
        }
        map<int, int> m1 = map<int, int>();
        map<int, list<int>> m2 = map<int, list<int>>();
        swap(totop[node], m1);
        swap(fromtop[node], m2);

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

    void ad(list<int> &a, list<int> &b){ //a+=b
        a.splice(a.begin(), 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]){
            list<int> l1 = list<int>{node};
            ad(fromtop[node][M+1], l1);
        }

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

            genFromTop(u.f, node);

            map<int, list<int>> 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());
                int R = -5;
                if(sz(change[u.s])){
                    R = change[u.s].back();
                }
                if(R <= it->f){
                    ad(newset[R], it->s);
                    fromtop[u.f].erase(it);
                }
                else break;
            }

            while(true){
                if(sz(fromtop[u.f]) == 0) break;
                auto it = fromtop[u.f].begin();
                assert(sz(change[u.s]) > 0);
                if(it->f < change[u.s][0]){
                    ad(newset[-5], it->s);
                    fromtop[u.f].erase(it);
                }
                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(r);
                    if(it == fromtop[u.f].end()) break;
                    if(it->f < l){
                        ad(newset[r], it->s);
                        fromtop[u.f].erase(it);
                    }
                    else break;
                }
            }
            swap(fromtop[u.f], newset);
            //fromtop contains all changed elements now
            for(auto x: fromtop[u.f]){
                ad(newset[x.f], x.s);
            }
            //newset has everything
            if(sz(fromtop[node]) < sz(newset)){
                swap(fromtop[node], newset);
            }
            for(auto x: newset){
                ad(fromtop[node][x.f], x.s);
            }

            ///////////////////

        }

        // 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: fromtop[R][x.f]){
                //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); }
                         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 20 ms 19328 KB Output is correct
2 Correct 16 ms 19200 KB Output is correct
3 Correct 17 ms 19200 KB Output is correct
4 Correct 15 ms 19200 KB Output is correct
5 Correct 17 ms 19200 KB Output is correct
6 Correct 32 ms 19840 KB Output is correct
7 Correct 325 ms 25720 KB Output is correct
8 Correct 336 ms 25848 KB Output is correct
9 Correct 324 ms 25720 KB Output is correct
10 Correct 6783 ms 89336 KB Output is correct
11 Correct 7190 ms 91524 KB Output is correct
12 Runtime error 933 ms 262148 KB Execution killed with signal 9 (could be triggered by violating memory limits)
13 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 1219 ms 262148 KB Execution killed with signal 9 (could be triggered by violating memory limits)
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 17 ms 19200 KB Output is correct
2 Correct 19 ms 19200 KB Output is correct
3 Correct 21 ms 19328 KB Output is correct
4 Correct 17 ms 19328 KB Output is correct
5 Correct 20 ms 19328 KB Output is correct
6 Correct 75 ms 27640 KB Output is correct
7 Runtime error 1489 ms 262148 KB Execution killed with signal 9 (could be triggered by violating memory limits)
8 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Runtime error 980 ms 262148 KB Execution killed with signal 9 (could be triggered by violating memory limits)
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 17 ms 19200 KB Output is correct
2 Correct 19 ms 19200 KB Output is correct
3 Correct 18 ms 19200 KB Output is correct
4 Correct 17 ms 19200 KB Output is correct
5 Correct 35 ms 19712 KB Output is correct
6 Correct 343 ms 25592 KB Output is correct
7 Execution timed out 8109 ms 92028 KB Time limit exceeded
8 Halted 0 ms 0 KB -