Cod sursa(job #2595165)

Utilizator CharacterMeCharacter Me CharacterMe Data 7 aprilie 2020 11:49:44
Problema Arbore Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 2.71 kb
#include <bits/stdc++.h>

using namespace std;
ifstream fin("arbore.in");
ofstream fout("arbore.out");

int n, m, l = -1, root, total;
int euler[100005], valPos[100005], valSeq[350];
pair<int, int> bound[100005];
bitset<1000001> forS[317];
bitset<100001> check;
vector<int> graph[100005];

void form_euler(int now);

void sameSeq(int lft, int rgt, int val);
void diffSeq(int lft, int rgt, int val);

int main()
{

    fin >> n >> m;
    root = int(sqrt(n));
    total = n / root;
    while(total * root < n) ++total;

    for(int i = 1; i < n; ++i){
        int x, y;
        fin >> x >> y;

        graph[x].push_back(y);
        graph[y].push_back(x);
    }

    form_euler(1);

    for(int i = 0; i < n; ++i){
        if(!(i % root)) {
            forS[i / root][0] = true;
        }
    }

    while(m--){
        int type;
        fin >> type;

        if(type == 1){
            int node, s;
            fin >> node >> s;

            if(bound[node].first / root == bound[node].second / root) {
                sameSeq(bound[node].first, bound[node].second, s);
            }
            else diffSeq(bound[node].first, bound[node].second, s);
        }
        else{
            int s;
            fin >> s;
            bool done = false;

            for(int i = 0; i < total; ++i){
                if(s >= valSeq[i] && forS[i][s - valSeq[i]]){
                    done = true;

                    for(int j = i * root; j < min((i + 1) * root, n); ++j){
                        if(valPos[j] + valSeq[i] == s){
                            fout << euler[j] << "\n";
                            break;
                        }
                    }

                    break;
                }
            }

            if(!done) fout << "-1\n";
        }
    }

    return 0;
}

void form_euler(int now){
    euler[++l] = now;
    bound[now].first = l;
    check[now] = true;

    for(auto next:graph[now]) {
        if(check[next]) continue;

        form_euler(next);
    }

    bound[now].second = l;
}

void sameSeq(int lft, int rgt, int val){
    int seq = lft / root;

    for(int i = root * seq; i < min(root * (seq + 1), n); ++i)
        forS[seq][valPos[i]] = false;

    for(int i = lft; i <= rgt; ++i)
       valPos[i] += val;

    for(int i = root * seq; i < min(root * (seq + 1), n); ++i)
        forS[seq][valPos[i]] = true;

}

void diffSeq(int lft, int rgt, int val){
    int seq = lft / root;
    sameSeq(lft, root * (seq + 1) - 1, val);
    lft = root * (seq + 1);

    seq = rgt / root;
    sameSeq(root * seq, rgt, val);
    rgt = root * seq - 1;

    for(int i = lft / root; i <= rgt / root; ++i)
        valSeq[i] += val;

}