hdu 5044 Tree (树链剖分+标记数组)
Posted kls123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 5044 Tree (树链剖分+标记数组)相关的知识,希望对你有一定的参考价值。
链接:http://acm.hdu.edu.cn/showproblem.php?pid=5044
这道题是真的有毒,之前用树链剖分+线段树写,tle了一万发,疯狂优化,最后放弃了,看了下其他人的题解
出题人卡了手线段树,不能用线段树写。。。。然后换成标记数组写(感觉比线段树要写起来要简单点。。),
然后还优化了输入。。结果还是TLE!!!!!
调试了一天多实在受不了了,交了发其他题解的代码上去。。。发现全部TLE。。。
就当自己这道题对了把。。。
实现代码:
#pragma comment(linker, "/STACK:1024000000,1024000000") #include<bits/stdc++.h> using namespace std; #define ll long long #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define mid int m = (l + r) >> 1 const int M = 2e5+10; struct node{ int to,next; }e[M]; int son[M],fa[M],head[M],siz[M],top[M],dep[M],tid[M],rk[M],a[M]; ll sum1[M],sum[M]; int cnt1,cnt,n; void add(int u,int v){ e[++cnt1].to = v;e[cnt1].next = head[u];head[u] = cnt1; e[++cnt1].to = u;e[cnt1].next = head[v];head[v] = cnt1; } void dfs1(int u,int faz,int deep){ dep[u] = deep; fa[u] = faz; siz[u] = 1; for(int i = head[u];i;i=e[i].next){ int v = e[i].to; if(v != fa[u]){ dfs1(v,u,deep+1); siz[u] += siz[v]; if(son[u] == -1||siz[v] > siz[son[u]]) son[u] = v; } } } void dfs2(int u,int t){ top[u] = t; tid[u] = cnt; rk[cnt] = u; //rk1[cnt] = wt[u]; cnt++; if(son[u] == -1) return; dfs2(son[u],t); for(int i = head[u];i;i = e[i].next){ int v = e[i].to; if(v != son[u]&&v != fa[u]) dfs2(v,v); } } void scan_d ( int& x , char c = 0 , int flag = 0 ) { while ( ( c = getchar () ) != ‘-‘ && ( c < ‘0‘ || c > ‘9‘ ) ) ; if ( c == ‘-‘ ) flag = 1 , x = 0 ; else x = c - ‘0‘ ; while ( ( c = getchar () ) >= ‘0‘ && c <= ‘9‘ ) x = x * 10 + c - ‘0‘ ; if ( flag ) x = -x ; } void change(int x,int y,int c){ int fx = top[x],fy = top[y]; while(fx != fy){ //cout<<1<<endl; if(dep[fx] < dep[fy]) swap(fx,fy),swap(x,y); sum[tid[fx]]+=c; sum[tid[x]+1] -= c; x = fa[fx]; fx = top[x]; } if(dep[x] > dep[y]) swap(x,y); sum[tid[x]] += c;sum[tid[y]+1]-=c; return ; } void change1(int x,int y,int c){ int fx = top[x],fy = top[y]; while(fx != fy){ if(dep[fx] < dep[fy]) swap(fx,fy),swap(x,y); sum1[tid[fx]]+=c,sum1[tid[x]+1]-=c; x = fa[fx]; fx = top[x]; } if(dep[x] > dep[y]) swap(x,y); sum1[tid[fx]+1]+=c;sum1[tid[x]+1]-=c; return ; } void init(){ memset(son,-1,sizeof(son)); memset(sum,0,sizeof(sum)); memset(sum1,0,sizeof(sum1)); memset(siz,0,sizeof(siz)); for(int i = 0;i <= n;i ++){ e[i].to=0;e[i].next=0;head[i]=0; } } int main() { int t,x,m,y,c,u[M],v[M]; scan_d(t); int t1 = t; while(t--){ init(); scan_d(n);scan_d(m); cnt1 = 1;cnt = 1; for(int i = 0;i < n-1;i ++){ scan_d(u[i]); scan_d(v[i]); add(u[i],v[i]); } dfs1(1,0,1);dfs2(1,1); char s[10]; while(m--){ scanf("%s",s); scan_d(x);scan_d(y);scan_d(c); if(s[3]==‘1‘) change(x,y,c); else change1(x,y,c); } printf("Case #%d:\n",t1-t); for(int i = 2;i <= n;i ++){ sum[i] += sum[i-1]; sum1[i] += sum1[i-1]; } for(int i = 1;i <= n;i ++){ if(i == n) printf("%lld\n",sum[tid[i]]); else printf("%lld ",sum[tid[i]]); } for(int i = 0;i < n-1;i ++){ if(dep[u[i]] > dep[v[i]]) swap(u[i],v[i]); if(i != n-2) printf("%lld ",sum1[tid[u[i]]]); else printf("%lld\n",sum1[tid[u[i]]]); } } return 0; }
以上是关于hdu 5044 Tree (树链剖分+标记数组)的主要内容,如果未能解决你的问题,请参考以下文章