Pagini recente » Cod sursa (job #2153897) | Cod sursa (job #10212) | Cod sursa (job #1958467) | Cod sursa (job #2820707) | Cod sursa (job #3232048)
#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, k; // 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
bool viz[nmax];
void dfs (int node){
subarb[node] = 1;
viz[node] = 1;
v[k] = node;
poz[node] = k++;
for (auto son : L[node]){
if (!viz[son]) {
dfs(son);
subarb[node] += subarb[son];
}
}
}
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 / sq + 1;
if (n % sq != 0) siz++;
st[0] = 0;
dr[0] = sq - 1;
for (int i = 1; i <= siz; ++i){
st[i] = st[i - 1] + sq;
dr[i] = dr[i - 1] + sq;
}
dr[siz - 1] = n - 1; // reparam capatul dreapta al ultimii bucati
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);
//k--;
for (int i = 0; i < siz; ++i)
fr[i][0] = dr[i] - st[i] + 1; // initial, valoarea 0 apare de st - dr + 1 ori (lungimea)
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;
}