hdu5044(树链剖分+标记法实现区间更新)
来源:互联网 发布:诚创cces电气设计软件 编辑:程序博客网 时间:2024/06/05 03:16
题意:一颗n个结点的树,两种操作: 1、将u到v之间的结点权值加k;2、将u到v之间的边权加k。输出经过修改后所有的边权和点权。
解题思路:做过树链剖分的应该都知道这题肯定是树链剖分题,其实就是一个模板题。但是注意点很多:1、结点有100000个,dfs的时候会爆栈,所以要扩栈; 2、这里的更新操作如果用线段树的update写,时间复杂度O(nlogn),会超时。 这里的成段更新很简单,而且是单点查询,只要用标记法就可以了,不需要用线段树。标记法时间复杂度O(n); 3、网上都说要输入优化才能过,所以我用读入优化写2078MS过的。不用输入优化也能过,时间3218MS。
代码如下:
#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring>#include<string>#include<vector>#define LL __int64#define N 100005#define inf 0x3f3f3f3f#define pi acos(-1.0)#define eps 10e-6using namespace std;int a[N][2],head[N];int tot;struct node{ int next,v,w;}edge[N*2];void addedge(int u,int v){ edge[tot].next = head[u]; edge[tot].v = v; head[u] = tot++;}//----------树链剖分----------------------int siz[N],son[N],dep[N],fa[N];void dfs1(int u,int pa,int depth){ siz[u] = 1; son[u] = 0; fa[u] = pa; dep[u] = depth; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; if(v == pa) continue; dfs1(v,u,depth+1); siz[u] += siz[v]; if(siz[v] > siz[ son[u] ]) son[u] = v; }}int top[N],w[N],dfs_clock;void dfs2(int u,int pa){ w[u] = ++dfs_clock; top[u] = pa; if(son[u]) dfs2(son[u],pa); for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; if(v != son[u] && v != fa[u]) dfs2(v,v); }}//------------标记法的区间更新------------------LL ans1[N],ans2[N];void change1(int x,int y,int k){ int f1 = top[x],f2 = top[y]; while(f1 != f2) { if(dep[f1] < dep[f2]) { swap(x,y); swap(f1,f2); } ans1[ w[f1] ] += k; ans1[ w[x]+1 ] -= k; x = fa[f1]; f1 = top[x]; } if(w[x] > w[y]) swap(x,y); ans1[ w[x] ] += k; ans1[ w[y]+1 ] -= k;}void change2(int x,int y,int k){ int f1 = top[x],f2 = top[y]; while(f1 != f2) { if(dep[f1] < dep[f2]) { swap(x,y); swap(f1,f2); } ans2[ w[f1] ] += k; ans2[ w[x]+1 ] -= k; x = fa[f1]; f1 = top[x]; } if(w[x] > w[y]) swap(x,y); ans2[ w[x]+1 ] += k; ans2[ w[y]+1 ] -= k;}inline bool scan_d(int &ret) { char c; int sgn; if(c=getchar(),c==EOF) return 0; //EOF while(c!='-'&&(c<'0'||c>'9')) c=getchar(); sgn=(c=='-')?-1:1; ret=(c=='-')?0:(c-'0'); while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0'); ret*=sgn; return 1;}int main(){ int t,cas = 1; // scanf("%d",&t); scan_d(t); while(t--) { int n,m; // scanf("%d%d",&n,&m); scan_d(n); scan_d(m); tot = 0; memset(head,-1,sizeof(head)); for(int i = 1; i < n; i++){ // scanf("%d%d",&a[i][0],&a[i][1]); scan_d(a[i][0]); scan_d(a[i][1]); addedge(a[i][0],a[i][1]); addedge(a[i][1],a[i][0]); } memset(siz,0,sizeof(siz)); dfs1(1,0,1); dfs_clock = 0; dfs2(1,1); memset(ans1,0,sizeof(ans1)); memset(ans2,0,sizeof(ans2)); while(m--) { char s[10]; int u,v,k; //scanf("%s%d%d%d",s,&u,&v,&k); scanf("%s",s); scan_d(u); scan_d(v); scan_d(k); if(s[3] == '1') change1(u,v,k); else change2(u,v,k); } for(int i = 2; i <= n; i++) { ans1[i] += ans1[i-1]; ans2[i] += ans2[i-1]; } printf("Case #%d:\n",cas++); int flag = 0; for(int i = 1; i <= n; i++) { if(flag == 0) printf("%I64d",ans1[ w[i] ]),flag = 1; else printf(" %I64d",ans1[ w[i] ]); } printf("\n"); flag = 0; for(int i = 1; i < n; i++) { if(dep[ a[i][0] ] < dep[ a[i][1] ]) swap(a[i][0],a[i][1]); if(flag == 0) printf("%I64d",ans2[ w[a[i][0]] ]),flag = 1; else printf(" %I64d",ans2[ w[a[i][0]] ]); } printf("\n"); } return 0;}
0 0
- hdu5044(树链剖分+标记法实现区间更新)
- HDU5044--Tree(树链剖分)
- HDU5044 Tree(树链剖分)
- hdu4970(后缀和,标记法的区间更新)
- hdu5044(神姿势+树链剖分)
- 树链剖分+离散+扫描(HDU5044)
- hdu5044 Tree(树链剖分+差分)
- Just a Hook (区间更新,lazy标记)
- hdu3966 or hdu5044 树链剖分
- 线段树区间更新区间求和(转延迟标记精讲)
- 线段树 & 区间更新 & 延时标记
- 线段树区间更新延迟标记
- 线段树区间更新 延时标记
- 2014上海网络预选赛1003(树链剖分)HDU5044
- UVA 11402 - Ahoy, Pirates!(线段树区间更新(标记重叠的处理))
- POJ 3468-A Simple Problem with Integers(线段树_区间更新+lazy标记)
- 杭电 HDU ACM 1698 Just a Hook(线段树 区间更新 延迟标记)
- Poj 3468 A Simple Problem with Integers(线段树 区间更新 延迟标记)
- 使用Spring Profile和Mybatis进行多个数据源(H2和Mysql)的切换
- android通过反射代替findViewById的过多使用
- 网络编程学习笔记(使用select函数的TCP和UDP回射服务器程序)
- HDU 5044 Tree(LCA)
- NOIP2012提高组day2第2题 借教室
- hdu5044(树链剖分+标记法实现区间更新)
- hdu 5045 费用流
- Ural 1009 K-based Numbers(DP)
- hibernate面试题
- css HTML里使用CSS 的几种方式
- java线程死锁
- 安装android L
- 《数据挖掘概念与技术》学习笔记
- PRD学习笔记