国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > 互联网 > HDU Tree LCA 2014 ACM/ICPC Asia Regional Shanghai Online

HDU Tree LCA 2014 ACM/ICPC Asia Regional Shanghai Online

来源:程序员人生   发布时间:2014-10-02 08:00:00 阅读次数:2806次

题意:

给定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: ", 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?' ':' '); } 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 */


生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生