Cod sursa(job #1866472)

Utilizator alexpetrescuAlexandru Petrescu alexpetrescu Data 3 februarie 2017 09:30:52
Problema Guvern Scor 0
Compilator cpp Status done
Runda Arhiva de probleme Marime 2.7 kb
#include <cstdio>
#include <cctype>
#include <vector>
#include <utility>
#include <algorithm>

#define x first
#define y second

#define BUF_SIZE 1<<17

#define MAXN 200000
#define MAXP 530000

int pos=BUF_SIZE;
char buf[BUF_SIZE];
FILE *fin;

std::vector <int> g[MAXN+1], u[MAXN+1], q[MAXN+1];
int t[MAXN+1], v[MAXN+1], st[MAXN+1], s[MAXN+1];
int k, h, n, d[MAXN+1], r[MAXN+1], e[MAXN+1];

std::pair <int, int> a[MAXN+2];

int poz, aint[MAXP];

inline char nextch(){
    if(pos==BUF_SIZE) fread(buf, BUF_SIZE, 1, fin), pos=0;
    return buf[pos++];
}

inline int read(){
    int x=0, s=1;
    char ch=nextch();
    while((!isdigit(ch))&&(ch!='-')) ch=nextch();
    if(ch=='-') ch=nextch(), s=-1;
    while(isdigit(ch)){
        x=10*x+ch-'0';
        ch=nextch();
    }
    return x*s;
}

void query(int p, int st, int dr){
    if((st==poz)&&(aint[p]==0)) poz=dr+1;
    else if(st<dr){
        int m=(st+dr)/2;
        if(poz<=m) query(2*p, st, m);
        if(m+1<=poz) query(2*p+1, m+1, dr);
    }
}

void update(int p, int st, int dr){
    if(st==dr) aint[p]^=1;
    else{
        int m=(st+dr)/2;
        if(poz<=m) update(2*p, st, m);
        else update(2*p+1, m+1, dr);
        aint[p]=aint[2*p]+aint[2*p+1];
    }
}

void dfs(int x){
    poz=v[x]+1;
    query(1, 1, n);
    u[a[poz].y].push_back(x);
    poz=v[x];
    update(1, 1, n);
    e[++h]=x;
    for(auto y:g[x]){
        if(y!=t[x]){
            t[y]=x;
            dfs(y);
        }
    }
    k++;
    r[x]=k;
    poz=v[x];
    update(1, 1, n);
}

int main(){
    FILE *fout;
    fin=fopen("guvern.in", "r");
    fout=fopen("guvern.out", "w");

    n=read();
    for(int i=1; i<n; i++){
        int x=read();
        int y=read();

        g[x].push_back(y);
        g[y].push_back(x);
    }

    for(int i=1; i<=n; i++)
        v[i]=read();

    for(int i=1; i<=n; i++)
        a[i]=std::make_pair(v[i], i);

    std::sort(a+1, a+n+1);

    for(int i=1; i<=n; i++)
        v[a[i].y]=i;

    for(int i=0; i<=n; i++)
        u[i].push_back(i);

    dfs(1);

    r[0]=n+1;

    for(int i=n; i>=0; i--){
        int x=e[i], vf=0;
        for(auto y:u[x]){
            while((vf>0)&&(r[y]>r[st[vf]]))
                vf--;
            if(vf>0)
                q[st[vf]].push_back(y);
            st[++vf]=y;
        }

        for(int j=u[x].size()-1; j>=0; j--){
            int y=u[x][j];
            s[y]=0;
            for(auto z:q[y])
                s[y]+=d[z];
            s[y]=std::max(s[y], d[y]);
            q[y].clear();
        }
        d[x]=1+s[x];
    }

    fprintf(fout, "%d\n", d[0]-1);

    fclose(fin);
    fclose(fout);
    return 0;
}