Cod sursa(job #3196214)

Utilizator Theo20067Cismaru Theodor-Alexe Theo20067 Data 23 ianuarie 2024 10:16:17
Problema Arbore Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.1 kb
#include <fstream>
#include <algorithm>
#include <vector>
#include <unordered_map>
#include <map>
#include <cmath>
using namespace std;
ifstream fin ("arbore.in");
ofstream fout("arbore.out");
int n,m,x,T,y,i,Q,k,p,s,rad,nrb;
int V[200003];///suma adaugata manual la numerele din bucket-urile capetelor
int S[603];/// suma pe bucket-urile intermediare
int E[200003],first[100003],last[100003];/// reprezentarea euler
vector <int> L[100003];
unordered_map <int,int> F[603];///frecventa numerelor din bucket-uri
inline int bucket(int x){ return x/rad+(x%rad!=0);}///bucketul in care se afla
inline int bucket_start(int x){ return (x-1)*rad+1;}///bucketul care urmeaza
void dfs(int x,int t)
{
    first[x]=++k;
    E[k]=x;
    for(auto j:L[x])
        if(j!=t)
            dfs(j,x);
    last[x]=++k;
    E[k]=x;
}
void update(int st,int dr,int val)
{
    int st1=bucket(st);
    int dr1=bucket(dr);
    if(st1==dr1)///daca sunt intr-un singur bucket
    {
        for(int j=st;j<=dr;j++)
        {
            F[st1][V[j]]--;///scad frecventa numarului curent
            if(F[st1][V[j]]<=0)
                F[st1].erase(V[j]);
            V[j]+=val;///adaug valoarea
            F[st1][V[j]]++;///updatez frecventa noua
        }
        return;
    }
    for(int j=st;j<bucket_start(st1+1);j++)///updatam bucket-ul capatului stang de la st pana la inceputul bucketului urmator (exclusiv)
    {
        F[st1][V[j]]--;
        if(F[st1][V[j]]<=0)
            F[st1].erase(V[j]);
        V[j]+=val;
        F[st1][V[j]]++;
    }
    for(int j=st1+1;j<dr1;j++)///bucket-urile intermediare sunt updatate cu s
        S[j]+=val;
    for(int j=bucket_start(dr1);j<=dr;j++)///updatam bucket-ul capatului drept de la inceputul bucketului pana la dr
    {
        F[dr1][V[j]]--;
        if(F[dr1][V[j]]<=0)
            F[dr1].erase(V[j]);
        V[j]+=val;
        F[dr1][V[j]]++;
    }
}
int query(int val)
{
    for(int j=1;j<=nrb;j++)///cautam in bucketuri
        if(F[j].find(val-S[j])!=F[j].end())///verificam daca exista valoarea ceruta in bucketul respectiv (valoarea ceruta = V[l]+S[l] asa ca cautam valoare-S[l]=V[l])
        {
            for(int l=bucket_start(j);l<bucket_start(j+1);l++)///cautam in bucket pozitia numarului
                if(V[l]+S[j]==val)
                    return E[l];///E retine valoarea fiecarui indice in reprezentarea euler
        }
    return -1;
}
int main()
{
    fin>>n>>m;
    for(i=1;i<n;i++)
    {
        fin>>x>>y;
        L[x].push_back(y);
        L[y].push_back(x);
    }
    dfs(1,0);
    rad=sqrt(k);///radicalul
    nrb=k/rad+(k%rad!=0);///nr bucket-uri
    for(i=1;i<=k;i++)
        F[bucket(i)][0]++;///initializam frecventa tuturor numerelor cu 1 la 0 caci toate sunt goale
    for(i=1;i<=m;i++)
    {
        fin>>T;
        if(T==1)
        {
            fin>>p>>s;
            update(first[p],last[p],s);///adaugam s la toate numerele din reprezentarea euler in intervalul first[p]->last[p]
        }
        else
        {
            fin>>s;
            fout<<query(s)<<"\n";///cautam s
        }
    }
    return 0;
}