这个题目 其实可以暴力 用两个 set 合并; 每次放进去一个元素只要找到这个元素第一个比他大的元素和最后一个比他小的元素;然后更新最优值;
证明为什么不会超时; 假如最后集合的小的为 S1,大的集合为S2; 这样将 S1合并到S2; 这样S2 》= S1×2;合并 t 次后 大小就成了 S1×(2^t); 但是集合大小只有N 个元素 也就是说 N 》= S1×(2^t ); 但S1等于1时 也就是说一个元素最多合并t 《= log(N) 次;
1 #include<iostream> 2 #include<stdio.h> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<set> 7 using namespace std; 8 9 struct date{ 10 int v,next; 11 }edge[51234]; int N,M,total,head[51234]; 12 void add_edge( int u,int v ){ 13 edge[total].v = v; 14 edge[total].next = head[u]; 15 head[u] = total++; 16 } 17 inline int min(int a,int b){return a<b?a:b;} 18 inline int max(int a,int b){return a>b?a:b;} 19 set<int>s[51234]; int res[51234]; int tab[51234]; 20 int dfs( int sta ) 21 { 22 bool fell = false; bool fall = false; int ans = 2147483647; 23 for( int i = head[sta]; i != -1; i = edge[i].next ) 24 { 25 int v = edge[i].v; ans = min( ans,dfs( v ) ); set<int>::iterator it,now; 26 if( !fell ){ tab[sta] = tab[v]; res[sta] = 2147483647; fell = true; continue; } 27 int len1 = s[tab[sta]].size(); int len2 = s[tab[v]].size(); 28 if( len1 > len2 ){ 29 for( it = s[tab[v]].begin(); it != s[tab[v]].end(); it++ ) 30 { 31 now = s[tab[sta]].lower_bound(*it); 32 if( now != s[tab[sta]].end() ){ ans = min( ans,*now-*it ); } 33 if( now != s[tab[sta]].begin() ){ now--;ans = min( ans,*it-*now ); } 34 if( s[tab[sta]].find(*it) == s[tab[sta]].end() ) s[tab[sta]].insert(*it); 35 } 36 }else { 37 for( it = s[tab[sta]].begin(); it != s[tab[sta]].end(); it++ ) 38 { 39 now = s[tab[v]].lower_bound(*it); 40 if( now != s[tab[v]].end() ){ ans = min( ans,*now-*it ); } 41 if( now != s[tab[v]].begin() ){ ans = min( ans,*it-*(--now) ); } 42 if( s[tab[v]].find(*it) == s[tab[v]].end() )s[tab[v]].insert(*it); 43 } 44 tab[sta] = tab[v]; 45 } 46 } 47 res[sta] = ans; return ans; 48 } 49 int main( ) 50 { 51 while( scanf("%d%d",&N,&M) != EOF ) 52 { 53 for( int i = 0; i <= N; i++ )s[i].clear(); 54 for( int i = 0; i <= N; i++ )tab[i] = i; 55 total = 0; int k = N-M+1; memset( head,-1,sizeof(head) ); 56 for( int i = 2; i <= N ;i++ ){ 57 int v; scanf("%d",&v); 58 add_edge( v,i ); 59 } 60 for( int i = 1; i <= M; i++ ){ 61 int num; scanf("%d",&num); s[k++].insert(num); 62 } 63 dfs( 1 ); 64 printf("%d",res[1]); 65 for( int i = 2; i <= N-M; i++ ) 66 printf(" %d",res[i]); 67 puts(""); 68 } 69 return 0; 70 }