Cod sursa(job #1495682)

Utilizator tamionvTamio Vesa Nakajima tamionv Data 3 octombrie 2015 13:38:55
Problema Arbore Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 3.28 kb
#include <fstream>
#include <iostream>
#include <vector>
#include <unordered_set>
#include <array>
#include <cmath>
#include <algorithm>
#include <bitset>
#include <stack>
using namespace std;

void make_euler(const vector<vector<int> >& vec,
    vector<int>& euler,
    vector<pair<int, int> >& st_fin){
	struct com{
		int prev, nod, copil; };
	stack<com> st;
	euler[0] = 1;
	st.push(com{0, 1, 0});
	for(int i = 1; i < euler.size(); ++i){
		if(st.top().copil >= vec[st.top().nod].size()){
			euler[i] = st.top().nod;
			st.pop(); }
		else{
			if(vec[st.top().nod][st.top().copil] == st.top().prev){
				++st.top().copil; }
			if(st.top().copil >= vec[st.top().nod].size()){
				euler[i] = st.top().nod; }
			else{
				euler[i] = vec[st.top().nod][st.top().copil];
				++st.top().copil;
				st.push(com{st.top().nod, st.top().copil-1, 0}); } } } }

				

constexpr int chunk_sz = 320;
 
class the_structure{
    const int nr_chunks;
    vector<int> buf, which_chunk;
    struct chunk_info{
        int st, dr;
		bitset<1000010> apare;
        int delta = 0; };
    vector<chunk_info> chunks;
    void redo_chunk(const int ch){
        chunks[ch].apare = 0;
        for(int i = chunks[ch].st; i <= chunks[ch].dr; ++i){
            chunks[ch].apare[buf[i]] = 1; } }
public:
    the_structure(const int n):
        nr_chunks(ceil(float(n)/chunk_sz)),
        buf(n), which_chunk(n), chunks(nr_chunks){
  
        for(int i = 0; i < nr_chunks; ++i){
            chunks[i].st = i*chunk_sz;
            chunks[i].apare[0] = 1;
            for(int j = 0; j < chunk_sz && j + chunks[i].st < n; ++j){
                which_chunk[chunks[i].st+j] = i; }
            chunks[i].dr = min(chunks[i].st + chunk_sz - 1, n-1); } }
      
    void update(const int st, const int dr, const int val){
        const int st_chunk = which_chunk[st], dr_chunk = which_chunk[dr];
        if(st_chunk != dr_chunk){
            for(int i = st; i <= chunks[st_chunk].dr; ++i){
                buf[i] += val; }
            for(int i = chunks[dr_chunk].st; i <= dr; ++i){
                buf[i] += val; }
            redo_chunk(st_chunk);
            redo_chunk(dr_chunk); }
        else{
            for(int i = st; i <= dr; ++i){
                buf[i] += val; }
            redo_chunk(st_chunk); }
        for(int i = st_chunk+1; i < dr_chunk; ++i){
            chunks[i].delta += val; } }
      
    int query(const int val){
        for(const auto& ch : chunks){
            if(ch.apare[val-ch.delta]){
                return distance(begin(buf),
                    find(begin(buf) + ch.st, begin(buf) + ch.dr + 1, val-ch.delta)); } }
        return -1; } };

int main(){
    ifstream f("arbore.in");
    ofstream g("arbore.out");
    int n, m;
    f >> n >> m;
    vector<vector<int> > vec(n+1);
    for(int i = 0, a, b; i < n-1; ++i){
        f >> a >> b;
        vec[a].push_back(b);
        vec[b].push_back(a); }
    vector<int> euler(2*n);
    vector<pair<int, int> > st_fin(n+1, {0, 0});
	make_euler(vec, euler, st_fin);
    the_structure ts(euler.size());
    for(int i = 0, t, p, s; i < m; ++i){
        f >> t;
        if(t == 1){
            f >> p >> s;
            ts.update(st_fin[p].first, st_fin[p].second, s); }
        else{
            f >> s;
            const int rez = ts.query(s);
            g << (rez != -1 ? euler[rez] : -1) << '\n'; } }
    return 0; }