Submission #603520

# Submission time Handle Problem Language Result Execution time Memory
603520 2022-07-24T07:46:32 Z 반딧불(#8427) Synchronization (JOI13_synchronization) C++17
0 / 100
253 ms 262144 KB
#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

struct Pair{
    int min, max;
    Pair(){}
    Pair(int min, int max): min(min), max(max){}

    Pair operator+(const Pair &r)const{
        return Pair(::min(min, r.min), ::max(max, r.max));
    }
};

struct segTree{
    Pair tree[800002];
    int lazy[800002];
    vector<vector<pair<int*, int> > > history;

    void init(int i, int l, int r){
        lazy[i] = 0;
        if(l==r){
            tree[i].min = tree[i].max = l;
            return;
        }
        int m = (l+r)>>1;
        init(i*2, l, m);
        init(i*2+1, m+1, r);
        tree[i] = tree[i*2] + tree[i*2+1];
    }

    void save(){
        history.push_back(vector<pair<int*, int> >());
    }

    void record(int &x){
        history.back().push_back(make_pair(&x, x));
    }

    void record(Pair &x){
        record(x.min), record(x.max);
    }

    void rollback(){
        for(int i=(int)history.back().size()-1; i>=0; i--){
            *(history.back()[i].first) = history.back()[i].second;
        }
        history.pop_back();
    }

    void propagate(int i, int l, int r){
        if(!lazy[i]) return;
        record(tree[i]);
        tree[i] = Pair(lazy[i], lazy[i]);
        if(l!=r){
            record(lazy[i*2]);
            record(lazy[i*2+1]);
            lazy[i*2] = lazy[i*2+1] = lazy[i];
        }
    }

    void update(int i, int l, int r, int s, int e, int v){
        propagate(i, l, r);
        if(r<s || e<l) return;
        if(s<=l && r<=e){
            record(lazy[i]);
            lazy[i] = v;
            propagate(i, l, r);
        }
        int m = (l+r)>>1;
        update(i*2, l, m, s, e, v);
        update(i*2+1, m+1, r, s, e, v);
        record(tree[i]);
        tree[i] = tree[i*2] + tree[i*2+1];
    }

    Pair query(int i, int l, int r, int s, int e){
        propagate(i, l, r);
        if(r<s || e<l) return Pair(1e9, 0);
        if(s<=l && r<=e) return tree[i];
        int m = (l+r)>>1;
        return query(i*2, l, m, s, e) + query(i*2+1, m+1, r, s, e);
    }

    int lower_bound(int i, int l, int r, int x){
        propagate(i, l, r);
        if(tree[i].max < x) return r+1;
        if(l==r) return l;
        int m = (l+r)>>1;
        if(query(i, l, m, l, m).max >= x) return lower_bound(i*2, l, m, x);
        else return lower_bound(i*2+1, m+1, r, x);
    }
};

struct Edge{
    int x, y, idx;
    Edge(){}
    Edge(int x, int y, int idx): x(x), y(y), idx(idx){}
};

int n, m, q;
int ex[100002], ey[100002];
vector<Edge> link[100002];
int arr[200002];
int query[100002];
vector<int> toggle[100002];
int ans[100002];

int root;
bool centroidUsed[100002];
int subTreeSize[100002];

segTree tree;
int tn;
vector<int> timeList;
vector<int> adjList;
int subroot[100002];
vector<int> subtreeList[100002];

int _g(int x){
    return lower_bound(timeList.begin(), timeList.end(), x) - timeList.begin();
}

void dfsSubtree(int x, int p=-1){
    subTreeSize[x] = 1;
    for(Edge y: link[x]){
        if(y.y==p || centroidUsed[y.y]) continue;
        for(int t: toggle[y.idx]) timeList.push_back(t);
        dfsSubtree(y.y, x);
        subTreeSize[x] += subTreeSize[y.y];
    }
}

int dfsFind(int x, int p, int lim){
    for(auto y: link[x]){
        if(y.y==p || centroidUsed[y.y]) continue;
        if(subTreeSize[y.y] >= lim) return dfsFind(y.y, x, lim);
    }
    return x;
}

void dfsGetList(int x, int p, vector<int> &vec, int r){
    vec.push_back(x);
    subroot[x] = r;
    subtreeList[r].push_back(x);
    for(auto y: link[x]){
        if(y.y==p || centroidUsed[y.y]) continue;
        dfsGetList(y.y, p, vec, r);
    }
}

int xtoc[100002], ctox[100002];

void update(int s, int e, int v){
    s = tree.lower_bound(1, 0, tn, s);
    e = tree.lower_bound(1, 0, tn, e+1) - 1;
    tree.update(1, 0, tn, s, e, v);
}

void dfsdp1(int x, int p=-1){ /// x���� c�� ���� ���� ���� �� ���
    xtoc[x] = tree.query(1, 0, tn, 0, tn).min;
    for(auto y: link[x]){
        if(y.y==p || centroidUsed[y.y]) continue;
        tree.save(); /// �� �ں��� ���׸�Ʈ Ʈ���� �����Ѵ�
        int prv = 0;
        for(int i=0; i<(int)toggle[y.idx].size(); i+=2){
            int sg = _g(toggle[y.idx][i]), eg = _g(toggle[y.idx][i+1]);
            update(prv, sg, tree.query(1, 0, tn, sg, sg).min);
            prv = eg;
        }
        tree.update(1, 0, tn, prv, tn, tn);
        dfsdp1(y.y, x); /// ���
        tree.rollback(); /// �ѹ�
    }
}

void dfsdp2(int x, int p=-1){
    ctox[x] = tree.lower_bound(1, 0, tn, tn) - 1;
    if(ctox[x] != tn) ans[x]++;
    for(auto y: link[x]){
        if(y.y==p || centroidUsed[y.y]) continue;
        tree.save();
        int prv = 0;
        for(int i=0; i<(int)toggle[y.idx].size(); i+=2){
            int sg = _g(toggle[y.idx][i]), eg = _g(toggle[y.idx][i+1]);
            update(prv, sg, sg);
            prv = eg;
        }
        tree.update(1, 0, tn, prv, tn, tn);
        dfsdp2(y.y, x);
        tree.rollback();
    }
}

void findCentroid(int x){
    /// ���� ��Ʈ���̵带 �����, �ð��� ���� ��ǥ ������ ����.
    timeList.clear();
    dfsSubtree(x);
    x = dfsFind(x, -1, (subTreeSize[x]+1)/2);
    centroidUsed[x] = 1;
    timeList.push_back(1e9);
    sort(timeList.begin(), timeList.end());
    timeList.erase(unique(timeList.begin(), timeList.end()), timeList.end());
    tn = (int)timeList.size()-1;

    /// ���� ��Ʈ���̵忡 ������ �������� ��ϰ� �� �Ʒ��� ����Ʈ���� ����� �̾� ����.
    adjList.clear();
    for(Edge e: link[x]){
        if(centroidUsed[e.y]) continue;
        adjList.push_back(e.y);
        subtreeList[e.y].clear();
        dfsGetList(e.y, x, subtreeList[e.y], e.y);
    }

    /// ���� ��Ʈ���̵忡������ dfs�� ���鼭, �� x�� ���� x->c�� �����ϴ� ���� ���� �ð��� ������.
    tree.init(1, 0, tn);
    dfsdp1(x);
    tree.init(1, 0, tn);
    dfsdp2(x);

    /// �ϼ��� ctox, xtoc �迭�� ���� ���� ������ �������. (c�� ���Ե� ���� ����)
    vector<int> xtocvec(tn+1), ctoxvec(tn+1);
    for(Edge e: link[x]) if(!centroidUsed[e.y]) for(auto y: subtreeList[e.y]){
        xtocvec[xtoc[y]]++;
        ctoxvec[ctox[y]]++;
    }
    for(int i=1; i<=tn; i++) xtocvec[i] += xtocvec[i-1];
    for(Edge e: link[x]) if(!centroidUsed[e.y]) for(auto y: subtreeList[e.y]){
        ans[y] += xtocvec[ctox[y]];
    }
    for(int i=tn; i>=1; i--) xtocvec[i] -= xtocvec[i-1];

    for(Edge e: link[x]) if(!centroidUsed[e.y]){
        vector<int> vec;
        for(auto y: subtreeList[e.y]) vec.push_back(xtoc[y]);
        sort(vec.begin(), vec.end());
        for(auto y: subtreeList[e.y]){
            ans[y] -= upper_bound(vec.begin(), vec.end(), ctox[y]) - vec.begin();
        }
    }

    /// ���� ��������� ����.
    for(Edge e: link[x]){
        if(!centroidUsed[e.y]) continue;
        findCentroid(e.y);
    }
}

int main(){
    scanf("%d %d %d", &n, &m, &q);
    for(int i=1; i<n; i++){
        scanf("%d %d", &ex[i], &ey[i]);
        link[ex[i]].push_back(Edge(ex[i], ey[i], i));
        link[ey[i]].push_back(Edge(ey[i], ex[i], i));
    }
    for(int i=1; i<=m; i++){
        scanf("%d", &arr[i]);
        toggle[arr[i]].push_back(i);
    }
    for(int i=1; i<=q; i++) scanf("%d", &query[i]);
    for(int i=1; i<n; i++) if(toggle[i].size() % 2) toggle[i].push_back(m+1);

    findCentroid(1);
    for(int i=1; i<=q; i++){
        printf("%d\n", ans[query[i]]);
    }
}

Compilation message

synchronization.cpp: In function 'int main()':
synchronization.cpp:252:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  252 |     scanf("%d %d %d", &n, &m, &q);
      |     ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~
synchronization.cpp:254:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  254 |         scanf("%d %d", &ex[i], &ey[i]);
      |         ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~
synchronization.cpp:259:14: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  259 |         scanf("%d", &arr[i]);
      |         ~~~~~^~~~~~~~~~~~~~~
synchronization.cpp:262:34: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  262 |     for(int i=1; i<=q; i++) scanf("%d", &query[i]);
      |                             ~~~~~^~~~~~~~~~~~~~~~~
# Verdict Execution time Memory Grader output
1 Runtime error 14 ms 14880 KB Execution killed with signal 11
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Runtime error 229 ms 262144 KB Execution killed with signal 9
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Runtime error 161 ms 262144 KB Execution killed with signal 9
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Runtime error 253 ms 262144 KB Execution killed with signal 9
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Runtime error 163 ms 262144 KB Execution killed with signal 9
2 Halted 0 ms 0 KB -