首页 > 代码库 > HDOJ 5044 Tree

HDOJ 5044 Tree


树链剖分裸题。。。。

又要扩栈又要输入挂还卡格式。。。。真无语

Tree

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 1538    Accepted Submission(s): 261


Problem Description
You are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are numbered from 1 to N

There are N - 1 edges numbered from 1 to N - 1.

Each node has a value and each edge has a value. The initial value is 0.

There are two kind of operation as follows:

● ADD1 u v k: for nodes on the path from u to v, the value of these nodes increase by k.

● ADD2 u v k: for edges on the path from u to v, the value of these edges increase by k.

After finished M operation on the tree, please output the value of each node and edge.
 

Input
The first line of the input is T (1 ≤ T ≤ 20), which stands for the number of test cases you need to solve.

The first line of each case contains two integers N ,M (1 ≤ N, M ≤105),denoting the number of nodes and operations, respectively.

The next N - 1 lines, each lines contains two integers u, v(1 ≤ u, v ≤ N ), denote there is an edge between u,v and its initial value is 0.

For the next M line, contain instructions “ADD1 u v k” or “ADD2 u v k”. (1 ≤ u, v ≤ N, -105 ≤ k ≤ 105)
 

Output
For each test case, print a line “Case #t:”(without quotes, t means the index of the test case) at the beginning.

The second line contains N integer which means the value of each node.

The third line contains N - 1 integer which means the value of each edge according to the input order.
 

Sample Input
2 4 2 1 2 2 3 2 4 ADD1 1 4 1 ADD2 3 4 2 4 2 1 2 2 3 1 4 ADD1 1 4 5 ADD2 3 2 4
 

Sample Output
Case #1: 1 1 0 1 0 2 2 Case #2: 5 0 0 5 0 4 0
 

Source
2014 ACM/ICPC Asia Regional Shanghai Online
 


#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>

#pragma comment(linker, "/STACK:1024000000,1024000000")

using namespace std;

const int maxn=100100;

int nextInt()
{
    char ch;
    int ok=0,fu=0,ans=0;
    while(ch=getchar())
    {
        if(ch=='-'||(ch>='0'&&ch<='9'))
        {
            ok=1;
            if(ch=='-') fu=1;
            else
            {
                ans=ans*10+(ch-'0');
            }
        }
        else if(ok==1) break;
    }
    if(fu) ans=-ans;
    return ans;
}

struct Edge
{
    int to,next;
}edge[maxn*2];

int Adj[maxn],Size;

void add_edge(int u,int v)
{
    edge[Size].to=v; edge[Size].next=Adj[u]; Adj[u]=Size++;
}

int fa[maxn],deep[maxn],num[maxn],son[maxn];
int top[maxn],p[maxn],rp[maxn],pos;
int tree[2][maxn],n,m;

inline int lowbit(int x)
{
    return x&(-x);
}

void ADD(int id,int p,int v)
{
    for(int i=p;i<=n;i+=lowbit(i))
        tree[id][i]+=v;
}

int SUM(int id,int p)
{
    int ret=0;
    for(int i=p;i;i-=lowbit(i))
        ret+=tree[id][i];
    return ret;
}

void init()
{
    memset(Adj,-1,sizeof(Adj));
    memset(son,-1,sizeof(son));
    memset(tree,0,sizeof(tree));
    Size=0;pos=1;
}

void dfs1(int u,int pre,int d)
{
    num[u]=1; fa[u]=pre; deep[u]=d;
    for(int i=Adj[u];~i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v==pre) continue;
        dfs1(v,u,d+1);
        num[u]+=num[v];
        if(son[u]==-1||num[son[u]]<num[v])
        {
            son[u]=v;
        }
    }
}

void getP(int u,int tp)
{
    top[u]=tp; p[u]=pos++; rp[p[u]]=u;
    if(son[u]!=-1) getP(son[u],tp);
    for(int i=Adj[u];~i;i=edge[i].next)
    {
        int v=edge[i].to;
        if(v!=fa[u]&&v!=son[u])
            getP(v,v);
    }
}

void Change(int u,int v,int k)
{
    int f1=top[u],f2=top[v];
    while(f1!=f2)
    {
        if(deep[f1]<deep[f2])
        {
            swap(f1,f2); swap(u,v);
        }
        ADD(0,p[f1],k); ADD(0,p[u]+1,-k);
        u=fa[f1]; f1=top[u];
    }
    if(deep[u]<deep[v]) swap(u,v);
    ADD(0,p[v],k); ADD(0,p[u]+1,-k);
}

void Change2(int u,int v,int k)
{
    int f1=top[u],f2=top[v];
    while(f1!=f2)
    {
        if(deep[f1]<deep[f2])
        {
            swap(f1,f2); swap(u,v);
        }
        ADD(1,p[f1]-1,k); ADD(1,p[u],-k);
        u=fa[f1]; f1=top[u];
    }
    if(u==v) return ;
    if(deep[u]<deep[v]) swap(u,v);
    ADD(1,p[son[v]]-1,k);
    ADD(1,p[u],-k);
}

int bian[maxn][2];

int main()
{
    int T_T,cas=1;
    scanf("%d",&T_T);
    while(T_T--)
    {
        init();
        scanf("%d%d",&n,&m);
        for(int i=0;i<n-1;i++)
        {
            int a,b;
            a=nextInt(); b=nextInt();
            add_edge(a,b);
            add_edge(b,a);
            bian[i][0]=a;bian[i][1]=b;
        }
        dfs1(1,0,0);
        getP(1,1);

        for(int i=0;i<n-1;i++)
        {
            if(deep[bian[i][0]]<deep[bian[i][1]])
                swap(bian[i][0],bian[i][1]);
        }

        while(m--)
        {
            char op[10];
            int a,b,c;
            scanf("%s",op);
            a=nextInt(); b=nextInt(); c=nextInt();
            if(op[3]=='1')
            {
                Change(a,b,c);
            }
            else if(op[3]=='2')
            {
                Change2(a,b,c);
            }
        }
        printf("Case #%d:\n",cas++);
        for(int i=1;i<=n;i++)
            printf("%d%c",SUM(0,p[i]),(i==n)?'\n':' ');
        for(int i=0;i<n-1;i++)
        {
            printf("%d%c",SUM(1,p[bian[i][0]]-1),(i==n-2)?'\n':' ');
        }
        if(n==1) putchar(10);
    }
    return 0;
}



HDOJ 5044 Tree