답안 #244120

# 제출 시각 아이디 문제 언어 결과 실행 시간 메모리
244120 2020-07-02T15:52:00 Z rqi 동기화 (JOI13_synchronization) C++14
30 / 100
8000 ms 86020 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);
        }
        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); }
                         ~~~~~~~^~~~~~~~~~~~~~~~~~~~~~
# 결과 실행 시간 메모리 Grader output
1 Correct 18 ms 21504 KB Output is correct
2 Correct 21 ms 21504 KB Output is correct
3 Correct 18 ms 21504 KB Output is correct
4 Correct 21 ms 21504 KB Output is correct
5 Correct 22 ms 21760 KB Output is correct
6 Correct 35 ms 21888 KB Output is correct
7 Correct 294 ms 24824 KB Output is correct
8 Correct 291 ms 24824 KB Output is correct
9 Correct 315 ms 24896 KB Output is correct
10 Correct 7102 ms 55016 KB Output is correct
11 Correct 7548 ms 55212 KB Output is correct
12 Correct 5046 ms 77732 KB Output is correct
13 Execution timed out 8031 ms 53220 KB Time limit exceeded
14 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Execution timed out 8041 ms 54644 KB Time limit exceeded
2 Halted 0 ms 0 KB -
# 결과 실행 시간 메모리 Grader output
1 Correct 18 ms 21504 KB Output is correct
2 Correct 17 ms 21504 KB Output is correct
3 Correct 21 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 41 ms 22144 KB Output is correct
7 Correct 347 ms 27128 KB Output is correct
8 Correct 5109 ms 77856 KB Output is correct
9 Correct 5149 ms 77804 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 5202 ms 78072 KB Output is correct
2 Correct 3909 ms 83132 KB Output is correct
3 Correct 3943 ms 85884 KB Output is correct
4 Correct 3940 ms 86020 KB Output is correct
# 결과 실행 시간 메모리 Grader output
1 Correct 19 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 18 ms 21504 KB Output is correct
5 Correct 33 ms 21888 KB Output is correct
6 Correct 309 ms 24952 KB Output is correct
7 Correct 7792 ms 55680 KB Output is correct
8 Correct 5357 ms 80440 KB Output is correct
9 Execution timed out 8048 ms 55396 KB Time limit exceeded
10 Halted 0 ms 0 KB -