Cod sursa(job #1500799)

Utilizator livliviLivia Magureanu livlivi Data 12 octombrie 2015 18:23:39
Problema Arbore Scor 5
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.78 kb
#include<cstdio>
#include<bitset>
#define S 1000000
#define N 100000
#define B 330
using namespace std;

int left[N+1];
int right[N+1];
int v[N+1];
int bonus[N+1];
int n;

int lst[N+1];
int urm[2*N+1];
int vecin[2*N+1];
bool viz[N+1];
int k;


int min(int a,int b){
    return (a<b) ? a : b;
}


class mazi{
private:
    bitset <S+1> sum;
    int st,dr;
    int add;

public:
    void init(int i){
        st=(i-1)*B+1;
        dr=min(i*B,n);
        add=0;
    }

    void clear(int s){
        sum[s]=false;
    }

    void Add(int s){
        add+=s;
    }

    void update(){
        int i;
        for(i=st;i<=dr;i++)
            sum[bonus[i]]=true;
    }

    int getLeft(){
       return st;
    }

    int getRight(){
        return dr;
    }

    bool isTrue (int s){
        return sum[s-add];
    }

    int find(int s){
        int i;
        for(i=st;i<=dr;i++)
            if (bonus[i]==s-add) return v[i];
        return -1;
    }
};


mazi b[B+1];


void initializare(){
    int i;

    for(i=1;i<=(n-1)/B+1;i++){
        b[i].init(i);
    }
}


void update(int nod,int s){
    int st=left[nod];
    int dr=right[nod];
    int i,lim;

    if ((dr-1)/B+1-((st-1)/B+1)<=1){
        for(i=st;i<=dr;i++){
            b[(i-1)/B+1].clear(bonus[i]);
            bonus[i]+=s;
        }

        b[(st-1)/B+1].update();
        if ((dr-1)/B+1!=(st-1)/B+1) b[(dr-1)/B+1].update();
    }
    else {
        lim=b[(st-1)/B+1].getRight();
        for(i=st;i<=lim;i++){
            b[(st-1)/B+1].clear(bonus[i]);
            bonus[i]+=s;
        }
        b[(st-1)/B+1].update();

        for(i=b[(dr-1)/B+1].getLeft();i<=dr;i++){
            b[(dr-1)/B+1].clear(bonus[i]);
            bonus[i]+=s;
        }
        b[(dr-1)/B+1].update();

        lim=(dr-1)/B;
        for(i=(st-1)/B+2;i<=lim;i++)
            b[i].Add(s);
    }
}


int query(int s){
    int i;

    for(i=1;i<=(n-1)/B+1;i++){
        if (b[i].isTrue(s)) return b[i].find(s);
    }

    return -1;
}


void adauga(int lista,int nod){
    k++;
    vecin[k]=nod;
    urm[k]=lst[lista];
    lst[lista]=k;
}


void parc(int nod=1){
    int p;

    viz[nod]=true;
    n++;
    v[n]=nod;
    left[nod]=n;

    p=lst[nod];
    while(p>0){
        if (viz[vecin[p]]==false) parc(vecin[p]);
        p=urm[p];
    }

    right[nod]=n;
}


int main(){
    freopen ("arbore.in","r",stdin);
    freopen ("arbore.out","w",stdout);
    int i,m,n1,n2,op;

    scanf ("%d%d",&n,&m);
    for(i=1;i<n;i++){
        scanf ("%d%d",&n1,&n2);
        adauga(n1,n2);
        adauga(n2,n1);
    }

    n=0;
    parc();
    initializare();

    for(i=1;i<=m;i++){
        scanf ("%d",&op);
        if (op==1){
            scanf ("%d%d",&n1,&n2);
            update(n1,n2);
        }
        else {
            scanf ("%d",&n1);
            printf ("%d\n",query(n1));
        }
    }

    return 0;
}