HDU 5044 Tree (2014年上海赛区网络赛C题)
2015-09-06 17:15
435 查看
1.题目描述:点击打开链接
2.解题思路:本题是树链剖分的入门题。关于树链剖分的讲解,可以参考该博客:点击打开链接 。本题要求对结点和边都执行add操作,如果用树链剖分,并结合线段树,执行每次操作的时间复杂度可以降为O((logn)^2)。
3.代码:
2.解题思路:本题是树链剖分的入门题。关于树链剖分的讲解,可以参考该博客:点击打开链接 。本题要求对结点和边都执行add操作,如果用树链剖分,并结合线段树,执行每次操作的时间复杂度可以降为O((logn)^2)。
3.代码:
#include<iostream> #include<algorithm> #include<cassert> #include<string> #include<sstream> #include<set> #include<bitset> #include<vector> #include<stack> #include<map> #include<queue> #include<deque> #include<cstdlib> #include<cstdio> #include<cstring> #include<cmath> #include<ctime> #include<cctype> #include<complex> #include<functional> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; #define me(s) memset(s,0,sizeof(s)) #define rep(i,n) for(int i=0;i<(n);i++) typedef long long ll; typedef unsigned int uint; typedef unsigned long long ull; typedef pair <int, int> P; const int N=100000+10; struct Edge { int to,next; }edge[N*2]; int head ,tot; int top ,fa ,dep ,son ,size ; int p ,fp ; int pos; void init() { tot=0,pos=1; memset(head,-1,sizeof(head)); memset(son,-1,sizeof(son)); } void add_edge(int u,int v) { edge[tot].to=v; edge[tot].next=head[u]; head[u]=tot++; } void dfs1(int u,int pre,int d)// 第一遍dfs求出fa, deep, num, son。其中u当前节点, pre为父节点, d为深度 { dep[u]=d; fa[u]=pre; size[u]=1; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].to; if(v!=pre) { dfs1(v,u,d+1); size[u]+=size[v]; if(son[u]==-1||size[v]>size[son[u]]) son[u]=v; } } } void dfs2(int u,int sp)// 第二遍dfs求出top和p,sp为当前点所在重链的顶节点 { top[u]=sp; p[u]=pos++; fp[p[u]]=u; if(son[u]==-1)return; dfs2(son[u],sp); for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].to; if(v!=son[u]&&v!=fa[u]) dfs2(v,v); } } ll seg [2]; void SegAdd(int L,int R,ll v,int d) { seg[L][d]+=v; seg[R+1][d]-=v; } void GetSeg(int L,int R,int d) { ll cur=seg[L][d]; for(int i=L+1;i<=R;i++) { ll t=seg[i][d]; seg[i][d]+=cur; cur+=t; } } void add1(int u,int v,int d) { int qd=0,qv=d; int ql,qr; while(top[u]!=top[v]) { if(dep[top[u]]<dep[top[v]])swap(u,v);// 对应区间是p[top[u]] -> p[u]; ql=p[top[u]],qr=p[u]; SegAdd(ql,qr,qv,qd); u=fa[top[u]]; } if(dep[u]>dep[v])swap(u,v); ql=p[u],qr=p[v]; SegAdd(ql,qr,qv,qd); } void add2(int u,int v,int d) { int f1=top[u],f2=top[v]; int qd=1,qv=d; int ql,qr; while(top[u]!=top[v]) { if(dep[top[u]]<dep[top[v]])swap(u,v); ql=p[top[u]],qr=p[u]; SegAdd(ql,qr,qv,qd); u=fa[top[u]]; } if(u==v)return; if(dep[u]>dep[v])swap(u,v); ql=p[son[u]],qr=p[v];// 注意区间是p[son[u]] -> p[v] SegAdd(ql,qr,qv,qd); } int eu ,ev ; char cmd[10]; int main() { int T; scanf("%d",&T); for(int kase=1;kase<=T;kase++) { int n,m; init(); printf("Case #%d:\n",kase); scanf("%d%d",&n,&m); for(int i=0;i<n-1;i++) { scanf("%d%d",&eu[i],&ev[i]); add_edge(eu[i],ev[i]); add_edge(ev[i],eu[i]); } dfs1(1,1,1); dfs2(1,1); me(seg); for(int i=0;i<m;i++) { int u,v,d; scanf("%s%d%d%d",cmd,&u,&v,&d); if(cmd[3]=='1') add1(u,v,d); else add2(u,v,d); } GetSeg(1,pos-1,0); GetSeg(1,pos-1,1); for(int i=1;i<=n;i++) printf("%I64d%c",seg[p[i]][0]," \n"[i==n]); for(int i=0;i<n-1;i++) { int u=eu[i],v=ev[i]; if(dep[u]<dep[v])swap(u,v); printf("%s%I64d",!i?"":" ",seg[p[u]][1]); } puts(""); } }
相关文章推荐
- HTTP网络协议(五)
- 从头开始实现一个神经网络
- Linux 网络编程学习---线程
- tomcat 配置https
- Socket连接与HTTP连接
- Android知识点5-Universal_image_loader加载网络图片
- Win7 网络连不上 提示 依赖服务或组无法启动
- android拍照并通过Http发送到Java后台
- 计算机网络学习之路01--概念详解
- 链路层网络编程技术
- ASIHTTPRequest类库简介和使用说明
- HDU - 1733 Escape(网络流层次模型)
- 网络负载问题
- HTTP协议简介2
- 快速Android开发系列网络篇之Android-Async-Http
- 对于System.Net.Http的学习(一)——System.Net.Http 简介
- 浏览器同源策略以及跨域请求时可能遇到的问题
- W5500 TCP/IP芯片 官方库文件阅读
- 博客已经迁移至 http://barretlee.com/entry/,时而同步分享到这里
- iOS开发网络--XML解析基础