Cod sursa(job #933328)

Utilizator visanrVisan Radu visanr Data 29 martie 2013 20:44:37
Problema Arbore Scor 100
Compilator cpp Status done
Runda Lista lui wefgef Marime 3.29 kb
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <bitset>
#include <algorithm>
using namespace std;

#define ChunkMax 350
#define Nmax 100010
#define ValMax 1000010
#define forit(it, v) for(typeof((v).begin()) it = (v).begin(); it != (v).end(); ++ it)
#define pb push_back

//Impart sirul de dupa liniarizare in bucati de sqrt(N) (chunk)
//Calculez marimea unui chunk si ce interval contine
//Tin ChunkSums[i][j] - 1 daca suma j apare in al i-lea chunk
//ChunkTotal[i] - cat am adunat la tot intervalul asociat chunk-ului i
//Cand fac update, daca tot intervalul chunk-ului e cuprins in intervalul de update, adaug la ChunkTotal
//Altfel refac sumele, adaugat la fiecare element dintr-un chunk ChunkTotal si, daca se poate, valoarea de update
//La query imi caut un chunk la care daca scad din suma de query ChunkTotal, sa fie o suma care apare in acel chunk
//Caut pozitia unde apare acea suma si returnez ce apare pe acea pozitie in liniarizare

int N, M, K, Type, Pos, Sum, X, Y, First[Nmax], Last[Nmax], Lin[Nmax];
int V[Nmax], ChunkTotal[ChunkMax], NrChunks, ChunkSize;
int LeftChunk[ChunkMax], RightChunk[ChunkMax];
bitset<ValMax> ChunkSums[ChunkMax];
vector<int> G[Nmax];

void DFS(int Node)
{
    First[Node] = ++ K;
    Lin[K] = Node;
    forit(it, G[Node])
        if(!First[*it])
            DFS(*it);
    Last[Node] = K;
}

void Build_Chunks()
{
    for(ChunkSize = 1; ChunkSize * ChunkSize <= N; ++ ChunkSize);
    ChunkSize --;
    for(int i = 1; i <= N; )
    {
        NrChunks ++;
        LeftChunk[NrChunks] = i;
        RightChunk[NrChunks] = min(i + ChunkSize - 1, N);
        ChunkSums[NrChunks][0] = 1;
        i += ChunkSize;
    }
}

void Update(int Left, int Right, int Sum)
{
    for(int i = 1; i <= NrChunks; ++ i)
    {
        if(LeftChunk[i] > Right) break;
        if(RightChunk[i] < Left) continue;
        if(Left <= LeftChunk[i] && RightChunk[i] <= Right)
        {
            ChunkTotal[i] += Sum;
            continue;
        }
        for(int j = LeftChunk[i]; j <= RightChunk[i]; ++ j)
        {
            ChunkSums[i][V[j]] = 0;
            V[j] += ChunkTotal[i];
            if(Left <= j && j <= Right) V[j] += Sum;
        }
        ChunkTotal[i] = 0;
        for(int j = LeftChunk[i]; j <= RightChunk[i]; ++ j)
            ChunkSums[i][V[j]] = 1;
    }
}

int Query(int Sum)
{
    for(int i = 1; i <= NrChunks; ++ i)
    {
        if(Sum < ChunkTotal[i]) continue;
        if(ChunkSums[i][Sum - ChunkTotal[i]])
            for(int j = LeftChunk[i]; j <= RightChunk[i]; ++ j)
                if(V[j] == Sum - ChunkTotal[i])
                    return Lin[j];
    }
    return -1;
}

int main()
{
    freopen("arbore.in", "r", stdin);
    freopen("arbore.out", "w", stdout);
    int i, j;
    scanf("%i %i", &N, &M);
    for(i = 1; i < N; ++ i)
    {
        scanf("%i %i", &X, &Y);
        G[X].pb(Y);
        G[Y].pb(X);
    }
    DFS(1);
    Build_Chunks();
    for(i = 1; i <= M; ++ i)
    {
        scanf("%i", &Type);
        if(Type == 1)
        {
            scanf("%i %i", &Pos, &Sum);
            Update(First[Pos], Last[Pos], Sum);
        }else
        {
            scanf("%i", &Sum);
            printf("%i\n", Query(Sum));
        }
    }
    return 0;
}