Cod sursa(job #3232045)

Utilizator Toni07Stoica Victor Toni07 Data 28 mai 2024 18:37:28
Problema Arbore Scor 30
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.19 kb
#include <bits/stdc++.h>
using namespace std;

ifstream f ("arbore.in");
ofstream g ("arbore.out");

const int nmax = 1e5 + 1, sqmax = 318;

unordered_map <int,int> fr[sqmax]; // de cate ori apare in bucata i valoarea j
vector<int> L[nmax]; // L vectorul de muchii
int m, n, sq, siz; // n, m, sqrt(n) si nr bucati
int subarb[nmax]; // nr de descendenti ai lui nod
int poz[nmax], sum[nmax], v[nmax]; // pozitia nodului in liniarizare si suma sa + indicele sau
int st[sqmax], dr[sqmax], sumbuc[sqmax]; // retin capetele stanga si dreapta & suma pe fiecare bucata

int i = 1;
void dfs (int node, int father){
  subarb[node] = 1;
  v[i] = node;
  poz[node] = i++;
  for (auto son : L[node]){
    if (son != father)
      dfs(son, node);
  }
  subarb[father] += subarb[node];
}
void update (int root, int val){
  int x = poz[root], y = x + subarb[root] - 1; // intervalul [x, y] acopera bucatile intre stbuc si drbuc
  int stbuc = (x / sq), drbuc = (y / sq);
  if (drbuc == stbuc){
    for (int i = x; i <= y; ++i){
      fr[drbuc][sum[i]]--; // scadem frecventa la fosta valoare
      if (fr[drbuc][sum[i]] == 0)
        fr[drbuc].erase (fr[drbuc].find (sum[i]));
      sum[i] += val; // crestem valoarea
      fr[drbuc][sum[i]]++; // crestem frecventa la valoarea noua
    }
  }
  else {
    for (int i = x; i <= dr[stbuc]; ++i){ // elementele singuratice din stanga
      fr[stbuc][sum[i]]--;
      if (fr[stbuc][sum[i]]==0)
        fr[stbuc].erase (fr[stbuc].find (sum[i]));
      sum[i] += val;
      fr[stbuc][sum[i]]++;
    }
    for (int i = y; i >= st[drbuc]; --i){ // elementele singuratice din dreapta
      fr[drbuc][sum[i]]--;
      if (fr[drbuc][sum[i]]==0)
        fr[drbuc].erase (fr[drbuc].find (sum[i]));
      sum[i] += val;
      fr[drbuc][sum[i]]++;
    }
    for (int i = stbuc + 1; i < drbuc; ++i){ // actualizam suma pe bucatile complete
      sumbuc[i] += val;
    }
  }
}

int query (int s){
  for (int i = 0; i <= siz; ++i){ // pt fiecare bucata
    if (fr[i].find (s - sumbuc[i]) != fr[i].end ()){ // daca avem solutie in bucata
      for (int sol = st[i]; sol <= dr[i]; ++sol){ // cautam in bucata
        if (sum[sol] == s - sumbuc[i]){ // valoarea s - sumbuc[i]
          return v[sol];
        }
      }
    }
  }
  return -1;
}

int main()
{
    f >> n >> m; // n = 73 => sq = 8 => siz = 10 (avem nevoie de fix 10 bucati, deci crestem siz)
    sq = sqrt(n); // n = 80 => sq = 8 => siz = 11 (nu mai crestem siz, tot 10 bucati avem nevoie)
    siz = (n - 1) / sq;
    for (int i = 0; i < siz; ++i){
      fr[i][0] = sq;
      st[i] = i * sq;
      dr[i] = (i + 1) * sq - 1;
      sumbuc[i] = 0;
    }
    st[siz] = siz * sq;
    dr[siz] = n - 1; // reparam capatul dreapta al ultimii bucati
    fr[siz][0] = n - sq * siz;
    sumbuc[siz] = 0;
    for (int i = 1; i < n; ++i){
      int x, y;
      f >> x >> y;
      L[x].push_back(y);
      L[y].push_back(x);
    }
    dfs(1,0);
    while (m--){
      int q;
      f >> q;
      if (q == 1){
        int root, val;
        f >> root >> val;
        update (root, val);
      }
      else {
        int s;
        f >> s;
        g << query(s) << "\n";
      }
    }
    return 0;
}