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;
}
时间: 2024-09-28 22:57:57

HDOJ 5044 Tree的相关文章

HDU 5044 Tree(树链剖分)

HDU 5044 Tree 题目链接 就简单的树链剖分,不过坑要加输入外挂,还要手动扩栈 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> using namespace std; const int N = 100005; #pragma comment(linker, "/STACK:1024000000,1024000000"

HDOJ 3516 Tree Construction

四边形优化DP Tree Construction Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 868    Accepted Submission(s): 470 Problem Description Consider a two-dimensional space with a set of points (xi, yi) t

HDOJ 2682 Tree(最小生成树prim算法)

Tree Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1954    Accepted Submission(s): 573 Problem Description There are N (2<=N<=600) cities,each has a value of happiness,we consider two cities

hdoj 2682 Tree(最小生成树)

Tree http://acm.hdu.edu.cn/showproblem.php?pid=2682 Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 1855    Accepted Submission(s): 544 Problem Description There are N (2<=N<=600) cities,each

HDOJ 5293 Tree chain problem LCA+树链剖分+树形DP

[题意] 给定一颗树上的几条链和每条链的权值,求能取出的不含有公共节点的链的最大权值.... [解] 预处理每条链的lca 树形DP, d[i]表示取到这个节点时可以得到的最大值 , sum[i]=sigma( d[k] | k 是i的子节点) 如果不取i  d[i]=sum[i] 如果取i , e是lca为i的链则 d[i]=max(d[i],e的权值+sigma(sum[k])-sigma(d[k]))  k为树链上的点 可以用树链剖分+树装数组在nlogn的时间复杂度内求链上的值 Tree

树链剖分 [HDU 5044] Tree

Tree Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 2038    Accepted Submission(s): 391 Problem Description You are given a tree (an acyclic undirected connected graph) with N nodes. The tree

HDU 5044 Tree 树链剖分

一棵树,初始边权和点权都为0 现在有m个操作,每一个操作: 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. 操作完后,输出每一个点的点权和每一条边的边权(边权按照输入顺序输出) 我们把边权也当做点权处

HDU 5044 TREE

题意:一棵树上两种操作,操作1,改变u到v的每一点的值增加k,操作2,改变u到v每一条边值增加k.最后结束时问,每一点和每一条边的值. 初始时,点和边的值都为0. 分析: 很显然要用树链剖分,将点和边分别划分成连续一段的编号,然后就是维护一段一段的值了,给它增加一个值,由于题目只需要输出最后结果,那么可以用树桩数组维护. 以边为例,对于l~r的每个值增加k,利用树桩数组v[i]表示第i个值与前一个值的差值,那么第k条边的值就是sum{v[i]| 1 <= i <= k},更新时则只要给v[l]

HDOJ 3516 Tree Construction 四边形优化dp

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3516 题意: 大概就是给你个下凸包的左侧,然后让你用平行于坐标轴的线段构造一棵树,并且这棵树的总曼哈顿距离最短 题解: 很容易得到转移方程: $$dp[i][j]=min \{ dp[i][k-1]+dp[k][j] + dis(uni(i,k-1),uni(k,j))\}$$ 其中$dp[i][j]$表示从$i$到$j$的最优解,$dis(i,j)$表示$i$和$j$之间的曼哈顿距离,$uni(i