HDU Tree LCA 2014 ACM/ICPC Asia Regional Shanghai Online

题意:

给定n个点的树,m个操作

树有点权和边权

下面n-1行给出树边

下面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.

跑个LCA,然后sum0[i]表示i 的点权,lazy0[i]表示 从[i,root] 这条路径上增加的值。

类似于前缀和的思想,最后dfs求个前缀和。

G++栈浅 && 开栈外挂无效,么么哒。。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <iostream>
#include <algorithm>
using namespace std;
typedef __int64 ll;
inline void rd(int &n){
    n = 0;
    char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') n *= 10, n += (c - '0'),c = getchar();
}
inline void rd64(ll &n){
    ll x = 0, tmp = 1;
    char c = getchar();
    while((c < '0' || c > '9') && c != '-' && c != EOF) c = getchar();
    if(c == '-') c = getchar(), tmp = -1;
    while(c >= '0' && c <= '9') x *= 10, x += (c - '0'),c = getchar();
    n = x*tmp;
}
int data[30];
inline void pt(ll n){
    if(n < 0)
        putchar('-'), n = -n;
    int len = 0;
    while(n)
        data[len++] = n%10, n /= 10;
    if(!len) data[len++] = 0;
    while(len--) putchar(data[len]+48);
}
#define N 100005
struct Edge{
    int to, nex;
}edge[2*N];
int head[N],edgenum,fa[N][20],dep[N];  //fa[i][x] 是i的第2^x个父亲(如果超过范围就是根)
void add(int u,int v){
    Edge E={v,head[u]};
    edge[edgenum] = E;
    head[u]=edgenum++;
}
void bfs(int root){
    queue<int> q;
    fa[root][0]=root;dep[root]=0;
    q.push(root);
    while(!q.empty()){
        int u=q.front();q.pop();
        for(int i=1;i<20;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
        for(int i=head[u]; ~i;i=edge[i].nex){
            int v=edge[i].to;if(v==fa[u][0])continue;
            dep[v]=dep[u]+1; fa[v][0]=u;
            q.push(v);
        }
    }
}
int Lca(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    for(int i=0;i<20;i++)if((dep[x]-dep[y])&(1<<i))x=fa[x][i];
    if(x==y)return x;
    for(int i=19;i>=0;i--)if(fa[x][i]!=fa[y][i])x=fa[x][i],y=fa[y][i];
    return fa[x][0];
}
void init(){memset(head, -1, sizeof head); edgenum = 0;}
int n, que;
ll sum0[N], lazy0[N], sum1[N], lazy1[N];
void dfs(int u, int Father){
    sum0[u] += lazy0[u];
    sum1[u] += lazy1[u];
    for(int i = head[u]; ~i; i = edge[i].nex) {
        int v = edge[i].to; if( v == Father ) continue;
        dfs(v, u);
        sum0[u] += lazy0[v];
        sum1[u] += lazy1[v];
        lazy0[u] += lazy0[v];
        lazy1[u] += lazy1[v];
    }
}
void input() {
    memset(sum0, 0, sizeof sum0);
    memset(sum1, 0, sizeof sum1);
    memset(lazy0, 0, sizeof lazy0);
    memset(lazy1, 0, sizeof lazy1);
    rd(n); rd(que);
    init();
    for(int i = 1; i < n; i++) {
        int u, v;
        rd(u); rd(v);
        add(u, v); add(v, u);
    }
    bfs(1);
}
int main() {
    int T, Cas = 1; rd(T);
    while (T -- )
    {
        input();
        printf("Case #%d:\n", Cas++);
        char op[6]; int l, r; ll val;
        while(que--){
            scanf("%s", op); rd(l); rd(r); rd64(val);
            if(dep[l] < dep[r]) swap(l, r); //让l在下面
            if(op[3] == '1')
            {
                int LCA = Lca(l, r);
                if(LCA == r) {
                    lazy0[l] += val; //从[l, 1]上增加val
                    lazy0[r] -= val;
                    sum0[r] += val;
                }
                else {
                    lazy0[l] += val;
                    lazy0[r] += val;
                    lazy0[LCA] -= val*2LL;
                    sum0[LCA] += val;
                }
            }
            else
            {
                int LCA = Lca(l, r);
                if(LCA == r) {
                    lazy1[l] += val; //从[l, 1]上增加val
                    lazy1[r] -= val;
                }
                else {
                    lazy1[l] += val;
                    lazy1[r] += val;
                    lazy1[LCA] -= val*2LL;
                }
            }
        }
        dfs(1, 1);
        for(int i = 1; i <= n; i++) {
            pt(sum0[i]);
            putchar(i==n?'\n':' ');
        }
        int fir = 0;
        for(int i = 0; i < edgenum; i+=2) {
            int u = edge[i].to, v = edge[i^1].to;
            if(dep[u] < dep[v])
                u = v;
            if(fir++)putchar(' ');
            pt(sum1[u]);
        }
        puts("");
    }
    return 0;
}
/*
99
9 4
1 2
2 3
3 5
5 6
5 7
2 4
4 8
4 9
ADD1 1 9 10
ADD1 1 7 5
ADD1 6 9 3
ADD1 8 7 100

5 4
1 2
2 3
2 4
2 5
ADD1 1 4 1
ADD1 5 3 1
ADD2 5 2 2
ADD2 2 4 1

*/
时间: 2024-08-08 21:06:13

HDU Tree LCA 2014 ACM/ICPC Asia Regional Shanghai Online的相关文章

HDU 5052 Yaoge’s maximum profit 裸树链剖分 2014 ACM/ICPC Asia Regional Shanghai Online

题意: 给定n个点的带点权树. 下面n行给出每个点点权表示每个点买卖鸡腿的价格 下面n-1行给出树边 下面Q个操作 Q行 u, v, val 从u走到v,过程中可以买一个鸡腿,然后到后面卖掉,输出max(0, 最大的收益) 然后给[u,v]路径上点点权+=val 思路: 树链剖分裸题 屌丝题解:点击打开链接 #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include &

HDU 5047 Sawtooth 规律+ C++大数模拟 2014 ACM/ICPC Asia Regional Shanghai Online

题意: 用x个大M 可以把平面分成至多几块. 就是折线切割平面的加强版. 一个简单的递推式 : F(x+1) = 16x+1+F(x) 然后转成通项公式,然后C++ 位压大数模拟 #include <cstdio> #include <iostream> #include <cstring> #include <algorithm> using namespace std; typedef long long ll; const int mod = 1000

2014 ACM/ICPC Asia Regional Shanghai Online

1012 the Sum of Cube Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 2407    Accepted Submission(s): 936 Problem Description A range is given, the begin and the end are both integers. You should

hdu5045||2014 ACM/ICPC Asia Regional Shanghai Online【数位dp】

大意:有n道题m个熊孩子,每个熊孩子对于每个题的正确率是已知的,对于每一道题必须有且只有一个熊孩子去做, 并且在任意时刻任意两个熊孩子的做的题数之差都不能大于等于2 比如有5个题三个熊孩子 那么1 2 3 3 1是合法的 但是12231是不合法的 求的是最大期望 分析: 题目已知熊孩子的数目最多是十个那么我们可以将其压缩成2进制(1024) dp[i][j]表示对于前i道题,状态为j的最大概率 那么&运算和|运算就能很好的处理这个问题 对于(1<<n - 1) 要将其清空 代码: 1

2014 ACM/ICPC Asia Regional Shanghai Online 1006 Sawtooth

<pre name="code" class="cpp">#include<iostream> #include<string> #include<iomanip> #include<algorithm> #include<cstring> #include<cstdio> using namespace std; #define MAXN 9999 #define MAXSIZE

HDU 5014 Number Sequence(2014 ACM/ICPC Asia Regional Xi&#39;an Online) 题解

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5014 Number Sequence Problem Description There is a special number sequence which has n+1 integers. For each number in sequence, we have two rules: ● ai ∈ [0,n] ● ai ≠ aj( i ≠ j ) For sequence a and sequ

hdu 5008(2014 ACM/ICPC Asia Regional Xi&#39;an Online ) Boring String Problem(后缀数组&amp;二分)

Boring String Problem Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 219    Accepted Submission(s): 45 Problem Description In this problem, you are given a string s and q queries. For each que

2014 ACM/ICPC Asia Regional Xi&#39;an Online(HDU 5007 ~ HDU 5017)

题目链接 A题:(字符串查找,水题) 题意 :输入字符串,如果字符串中包含“ Apple”, “iPhone”, “iPod”, “iPad” 就输出 “MAI MAI MAI!”,如果出现 “Sony” 就输出“SONY DAFA IS GOOD!” ,大小写敏感. 思路 : 字符串查找,水题. 1 #include <string.h> 2 #include <stdio.h> 3 #include <iostream> 4 5 using namespace st

HDU 5014 Number Sequence 贪心 2014 ACM/ICPC Asia Regional Xi&#39;an Online

尽可能凑2^x-1 #include <cstdio> #include <cstring> const int N = 100005; int a[N], p[N]; int init(int x) { int cnt = 0; while(x > 1) { x /= 2; cnt ++; } return cnt + 1; } int main() { int n; while(~scanf("%d", &n)){ for(int i = 0;