Cod sursa(job #973005)

Utilizator Impaler_009Mihai Nitu Impaler_009 Data 13 iulie 2013 02:56:52
Problema Heavy Path Decomposition Scor 0
Compilator cpp Status done
Runda Arhiva educationala Marime 4.63 kb
#include <fstream>
#include <vector>
#include <algorithm>
#include <bitset>
#define maxn 100001

using namespace std;

ifstream fin("heavypath.in");
ofstream fout("heavpath.out");

int value[maxn],depth[maxn]; // indexed by individual nodes in the graph
int parent[maxn],which_path[maxn],segment_tree_pos[maxn],path_length[maxn]; // indexed by the decomposed paths which can be n-1 in the worst case
int segment_tree [4*maxn];  //is actually a conglomerate of segment tress (one for each decomposed path) fitted into one array, the "nx4" size makes sure there is enough space for everything
int x,y,n,m,total_paths;
bool op;

vector <int> G[maxn],P[maxn];
bitset <maxn> visited;

int DFS (int x)
{
    visited[x]=1;

    bool leaf=1;
    int sum_nodes_below=0,child_nodes=0,heaviest_path=0,heaviest_child;

    for (vector<int>::iterator it= G[x].begin(); it!=G[x].end(); ++it)
    {
        if (visited[*it]) continue;

        leaf=0;
        depth[*it]=depth[x]+1;

        child_nodes = DFS (*it);
        sum_nodes_below  += child_nodes;
        if (child_nodes > heaviest_path)
        {
            heaviest_path=child_nodes;
            heaviest_child=*it;
        }
    }

    if (leaf)
    {
        ++total_paths;
        P[total_paths].push_back (x);
        path_length[total_paths]=1;
        which_path [x]=total_paths;
        return 1;
    }

    P[which_path[heaviest_child]].push_back (x);
    path_length[which_path[heaviest_child]]++;
    which_path[x] = which_path[heaviest_child];

    for (vector<int>::iterator it=G[x].begin(); it!=G[x].end(); it++)
    {
        if (*it==heaviest_child || depth[*it]<depth[x]) continue;
        parent[which_path[*it]]=x;
    }

    return sum_nodes_below+1;
}

void build_segment_tree (int node, int left, int right, int jump, int path)
{
    if (left==right)
    {
        segment_tree[node+jump]=value[P[path][left-1]];
        return;
    }

    int mid = (left+right)/2;
    build_segment_tree (node*2,left,mid,jump,path);
    build_segment_tree (node*2+1,mid+1,right,jump,path);

    segment_tree[node+jump] = max (segment_tree[node*2 + jump],segment_tree[node*2 + 1 + jump]);
}

void make_paths ()
{
    depth[1]=1;
    DFS (1);

    segment_tree_pos[1]=1;

    for (int i=1; i<=total_paths; i++)
    {
        reverse (P[i].begin(),P[i].end());

        if (i>1) segment_tree_pos[i] = segment_tree_pos[i-1] + 4*path_length[i-1];
        build_segment_tree (1, 1, path_length[i],segment_tree_pos [i],i);
    }
}

void update (int node, int left, int right, int target, int val, int jump)
{
    if (left==right) {segment_tree[node+jump] = val; return;}

    int mid = (left + right)/2;

    if (target<=mid) update (node*2,left,mid,target,val,jump);
    else update (node*2+1,mid+1,right,target,val,jump);

    segment_tree[node+jump]=max (segment_tree[node*2+jump],segment_tree[node*2+1+jump]);
}

int query (int node, int left, int right, int left_target, int right_target, int jump)
{
    if (left_target<=left && right_target>=right) return segment_tree[node+jump];

    int mid = (left+right)/2,maxv=0;

    if (left_target<=mid) maxv = max (maxv,query(node*2,left,mid,left_target,right_target,jump));
    if (right_target>mid) maxv = max (maxv,query(node*2+1,mid+1,right,left_target,right_target,jump));

    return maxv;
}

void operation (bool type, int x, int y)
{
    int target,path,target1,target2;

    if (!type)
    {
        target = depth[x] - depth[parent[which_path[x]]];
        update (1,1,path_length[which_path[x]],target,y,segment_tree_pos[which_path[x]]);
    }
    else
    {
        int maxv=0;
        while (which_path[x]!=which_path[y])
        {
            if (depth[parent[which_path[x]]] < depth[parent[which_path[y]]]) swap (x,y);
            target = depth[x] - depth[parent[which_path[x]]];
            maxv = max (maxv, query(1,1,path_length[which_path[x]],1,target,segment_tree_pos[which_path[x]]));
            x=parent[which_path[x]];
        }
        target1 = depth[x] - depth[parent[which_path[x]]];
        target2 = depth[y] - depth[parent[which_path[y]]];
        if (target1>target2) swap (target1,target2);
        maxv = max (maxv, query(1,1,path_length[which_path[x]],target1,target2,segment_tree_pos[which_path[x]]));
        fout<<maxv<<"\n";
    }
}

int main()
{
    fin>>n>>m;
    for (int i=1; i<=n; i++) fin>>value[i];
    for (int i=1; i<n; i++)
    {
        fin>>x>>y;
        G[x].push_back(y);
        G[y].push_back(x);
    }

    make_paths ();

    for (int i=1; i<=m; i++)
    {
        fin>>op>>x>>y;
        operation (op,x,y);
    }
}