暴力N^2 各種TLE
#include <cstdio>
#include <string.h>
const int maxn=100010;
struct node
{
int v;
node *next;
node (int a ,node * p):v(a),next(p){};
};
node * List[maxn];
int min_num[maxn],deg[maxn],n,son[maxn];
int n2;
bool vis [maxn];
void dfs (int u)
{
vis[u]=true ;
if(!(deg[u]^1))return ;
int v,i;
int pre=0,back=0,tmp=0;
if(u<n2)
{
for (i=0 ; i<u ; i++)
if(vis[i])pre++;
}
else
{
for(i=u+1 ; i<n ; i++)
if(vis[i])pre++;
}
node * p =List[u];
for (; p!=NULL ; p=p->next)
{
v=p->v;
//printf("u=%d v=%d \n",u,v);
if(!vis[v])
{
dfs(v);
son[u]+=son[v];
}
}
if(u<n2)
{
for (i=0 ; i<u ; i++)
if(vis[i])back++;
min_num[u]=back-pre;
}
else
{
for (i=u+1 ; i<n ; i++)
if(vis[i])back++;
min_num[u]=son[u]-back+pre-1;
}
//printf("%d,%d %d %d\n",pre,back,u ,son[u]);
}
void init ()
{
memset (List , 0 , sizeof(List));
memset (deg , 0 , sizeof(deg));
memset (vis , 0 , sizeof(vis));
n2=n/2;
}
int main ()
{
int p,i,j,u,v;
node *tmp1 ;
node *tmp2 ;
while (scanf("%d%d",&n,&p)==2 && (n||p))
{
init();
for (i=1 ; i<n ; ++i)
{
scanf("%d%d",&u,&v);
u-- , v--;
tmp1=new node(v,NULL);
List[u]==NULL?List[u]=tmp1:(tmp1->next=List[u],List[u]=tmp1);
/*tmp2=new node(u,NULL);
List[v]==NULL?List[v]=tmp2:(tmp2->next=List[v],List[v]=tmp2);*/
deg[u]++;deg[v]++;
son[i]=1;
}
son[0]=0;
p--;
vis[p]=true ;
node * tp=List[p];
min_num[p]=p;
for (; tp!=NULL ; tp=tp->next)
{
v=tp->v;
if(!vis[v])
dfs(v);
}
for (int i=0 ; i<n ; ++i)
printf("%d%c",min_num[i],i==n-1?'\n':' ');
}
return 0;
}
正解演算法 用樹狀數組
題 目 大 意 是 給 定 一 棵 樹 ,對 於 每 個 節 點 ,計 算 其 所 有 子 節 點 中 編 號 小 於 該 節 點 編 號 的 個
數 。 記 所 求 為 f[i], 根 據 樹 的 遞 歸 性 質 我 們 可 以 想 到 對 其 進 行 遞 歸 統 計 。 我 們 可 以 使 用 一 個
樹 狀 數 組 記 錄 當 前 加 入 的 節 點 。 每 當 遍 曆 到 一 個 節 點 時 ( 注 意 是 後 序 ), 便 將 該 節 點 加 入 ,
那 麼 當 我 們 遍 曆 完 以 V 為 根 的 所 有 子 樹 時 , 便 可 以 根 據 加 入 的 節 點 計 算 出 f[v ]。
這 裡 有 一 個 小 問 題 :假 設 U ,V 為 兄 弟 節 點 ,我 們 首 先 遍 曆 了 以 U 為 根 的 子 樹 ,當 我 們
遍 曆 以 V 為 根 的 子 樹 時 ,U 子 樹 的 所 有 節 點 已 經 加 入 了 ,然 而 它 們 並 不 屬 於 V 中 任 意 節 點 的
子 節 點 。 但 注 意 到 V 的 所 有 子 節 點 都 是 在 遍 曆 到 V 子 樹 之 後 才 加 入 的 , 所 以 我 們 可 以 在 遍
曆 V 節 點 的 子 節 點 之 前 記 錄 當 前 編 號 小 於 V 的 節 點 總 數 C 1 , 在 遍 曆 完 所 有 子 樹 之 後 計 算 編
號 小 於 V 的 節 點 總 數 C 2, 則 有 f[v ]= C 2-C 1 。