Cod sursa(job #1951941)

Utilizator GinguIonutGinguIonut GinguIonut Data 3 aprilie 2017 21:12:31
Problema Arbore Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 2.26 kb
#include <fstream>
#include <vector>
#include <cmath>

#define sqnMax 340
#define nMax 100001
#define sMax 1000001
#define pb push_back

using namespace std;

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

int n, nrQuery, sqn, nrBlocks, nrE;
int first[nMax], which[nMax], last[nMax], sumNode[nMax], addBlock[sqnMax];
bool have[sqnMax][sMax];
vector<int> G[nMax];

void depthFirstSearch(int node, int tata)
{
    first[node]=++nrE;
    which[nrE]=node;
    for(vector<int>::iterator it=G[node].begin(); it!=G[node].end(); it++)
        if(*it!=tata)
            depthFirstSearch(*it, node);
    last[node]=nrE;
}

int getBlock(int ind)
{
    if(ind%sqn==0)
        return ind/sqn;
    return (ind/sqn)+1;
}

void upDateBlock(int block)
{
    for(int i=(block-1)*sqn+1; i<=min(block*sqn, n); i++)
        have[block][sumNode[i]]=1;
}

void upDate(int node, int val)
{
    int block1=getBlock(first[node]), block2=getBlock(last[node]);
    for(int i=first[node]; getBlock(i)==block1 && i<=last[node]; i++)
    {
        sumNode[i]+=val;
        have[block1][sumNode[i]-val]=0;
    }
    upDateBlock(block1);

    for(int i=block1+1; i<block2; i++)
        addBlock[i]+=val;
    if(block1!=block2)
    {
        for(int i=(block2-1)*sqn+1; i<=last[node]; i++)
        {
            sumNode[i]+=val;
            have[block2][sumNode[i]-val]=0;
        }
        upDateBlock(block2);
    }
}

int getNode(int block, int sum)
{
    for(int i=(block-1)*sqn+1; i<=min(block*sqn, n); i++)
        if(sumNode[i]==sum)
            return which[i];
}

int query(int sum)
{
    for(int i=1; i<=nrBlocks; i++)
        if(sum-addBlock[i]>=0 && have[i][sum-addBlock[i]])
            return getNode(i, sum-addBlock[i]);
    return -1;
}

int main()
{
    int op, a, b;
    fin>>n>>nrQuery;
    for(int i=1; i<n; i++)
    {
        fin>>a>>b;
        G[a].pb(b);
        G[b].pb(a);
    }

    depthFirstSearch(1, 0);

    sqn=sqrt(n);
    nrBlocks=n/sqn;
    if(n%sqn!=0)
        nrBlocks++;

    for(int i=1; i<=nrQuery; i++)
    {
        fin>>op;
        if(op==1)
        {
            fin>>a>>b;
            upDate(a, b);
            continue;
        }
        fin>>a;
        fout<<query(a)<<'\n';
    }
}