题意:
看图说话,一棵锦标赛树(具体不描述,看DS书去),问每个队员的最好名次和最坏名次
分析:
求最好名次应该从上向下划分状态,而求最坏名次从下向上划分状态,举个例子吧,看第三排第一个1,它的最坏名次是第四排第一个1的最坏名次加上它的1^n-右孩子的最坏名次-1,而它的最好名次则是第二排第一个1的最好名次,它旁边那个3的最好名次就是3的父节点(1)的最好名次+1,大概明白什么意思了吧?看代码吧~。
代码:
1 # include <cstdio>
2 # include <cstring>
3 using namespace std;
4 # define max(a,b) ((a)>(b)?(a):(b))
5 # define min(a,b) ((a)<(b)?(a):(b))
6 int tree[1024],n;
7 int worst[1024],best[1024],high[1024],low[1024];
8 int main()
9 {
10 while(true)
11 {
12 scanf("%d",&n);
13 if(!n) break;
14 for(int i=1<<n;i<1<<(n+1);i++)
15 tree[i]=1+i-(1<<n),worst[i]=1<<n;
16 for(int t=n-1;t>=0;t--)
17 for(int i=1<<t;i<1<<(t+1);i++)
18 {
19 scanf("%d",tree+i);
20 worst[i]=(tree[i]==tree[i<<1]?worst[i<<1]-(1<<n)+worst[(i<<1)+1]:worst[(i<<1)+1]-(1<<n)+worst[i<<1])-1;
21 }
22 best[1]=1;
23 for(int i=2;i<1<<(n+1);i++)
24 best[i]=(tree[i]==tree[i>>1]?best[i>>1]:best[i>>1]+1);
25 for(int i=1;i<1<<(n+1);i++)
26 high[i]=low[i]=1<<n;
27 for(int i=1;i<1<<(n+1);i++)
28 {
29 high[tree[i]]=min(high[tree[i]],best[i]);
30 low[tree[i]]=min(low[tree[i]],worst[i]);
31 }
32 scanf("%d",&n);
33 while(n--)
34 {
35 int t;
36 scanf("%d",&t);
37 printf("Player %d can be ranked as high as %d or as low as %d.\n",t,high[t],low[t]);
38 }
39 printf("\n");
40 }
41 return 0;
42 }