1. 程式人生 > >hdu 5044 Tree (樹鏈剖分+標記數組)

hdu 5044 Tree (樹鏈剖分+標記數組)

chan main while class #define AR spa def ble

鏈接: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 (樹鏈剖分+標記數組)