hdu 4366 Successor (线段树 2012 Multi-University Training Contest 7 )

http://acm.hdu.edu.cn/showproblem.php?pid=4366

 

 

题意:

给你 n个点。他们有 上下级关系,一个点只有一个上级,一个上级 可以有多个下级,每个点有两个属性,能力值 、忠诚度(每个节点的忠诚度不同),求我们要删除 一个节点, 则我们 需从 其下级中选出 一个节点,其能力值 比该节点 要高,且 忠诚度是(比其能力高的下级节点中的)最高

 

 

题解:

首先将树状结构,转化为 线状结构,

可以遍历一遍将树上每个点标记为一维区间上的某个点,且在同一棵子树内的点是连续的一段。

然后,将所有点按能力从大到小排序,能力相同的编号小的排在前面,然后扫描一遍,扫描时维护一颗线段树,

(我们先插入线段树的是,比其能力值 大的,我们只要从这些里面找到,忠诚度最高的就 可以了)

先查找该点为根节点的子树内的最优值,然后插入该点的忠诚度。

 

 

  1 #include<stdio.h>
  2 #include<iostream>
  3 #include<algorithm>
  4 #include<cstring>
  5 #include<cmath>
  6 #include<queue>
  7 #include< set>
  8 #include<map>
  9  #define Min(a,b)  a>b?b:a
 10  #define Max(a,b)  a>b?a:b
 11  #define CL(a,num)  memset(a,num,sizeof(a));
 12  #define inf 9999999
 13  #define maxn    100110
 14  #define mod 100000007
 15  #define eps  1e-6
 16  #define ll  long long
 17  #define M   15520
 18  using  namespace std;
 19 map< int, int>map1;
 20 vector< int>g[maxn] ;
 21  int num ,ans[maxn],n,m,l[maxn],r[maxn];
 22  struct staff
 23 {
 24      int loy;
 25      int abt;
 26      int id;
 27 }sta[maxn];
 28  struct node
 29 {
 30      int l;
 31      int r;
 32      int mx;
 33 }p[maxn *  2];
 34  bool cmp (staff a, staff b)
 35 {
 36      return a.abt > b.abt ;
 37 }
 38  void dfs( int x) // 编号变为线状结构
 39  {
 40 
 41     l[x] = num++;
 42      for( int i =  0; i < g[x].size(); ++i)
 43     {
 44         dfs(g[x][i]);
 45     }
 46 
 47     r[x] = num ;
 48 
 49 }
 50  void build( int x, int l, int r)
 51 {
 52     p[x].l = l;
 53     p[x].r = r;
 54     p[x].mx = - 1 ;
 55      if(l == r)  return  ;
 56      int mid = (l + r) / 2;
 57     build(x* 2,l,mid);
 58     build(x* 2+ 1,mid +  1,r);
 59 
 60 }
 61  int  get( int x, int l, int r)
 62 {
 63 
 64      if( r < l )  return  - 1 ;
 65      if(p[x].l == l && p[x].r == r)
 66     {
 67 
 68          return p[x].mx;
 69     }
 70      int mid = (p[x].l + p[x].r) / 2 ;
 71      if(r <= mid)   return  get(x *  2,l,r);
 72      else
 73     {
 74          if(l > mid)  return  get(x *  2 +  1,l,r);
 75          else
 76         {
 77              return max( get(x *  2,l,mid), get(x *  2 +  1,mid +  1,r));
 78         }
 79     }
 80 }
 81  void insert( int x, int pos, int d)
 82 {
 83      if(p[x].l == p[x].r )
 84     {
 85         p[x].mx = d;
 86          return ;
 87 
 88     }
 89      int mid = (p[x].l + p[x].r) / 2 ;
 90      if(pos <= mid) insert(x* 2,pos,d);
 91      else
 92     {
 93        insert(x* 2 +  1, pos,d);
 94 
 95     }
 96 
 97     p[x].mx = max(p[x* 2].mx,p[x* 2+ 1].mx);
 98 
 99 }
100  void init()
101 {
102       forint i =  0; i <= n;++i )
103           g[i].clear();
104 
105     map1.clear();
106 
107     num =  0 ;
108 }
109  int main()
110 {
111      int t,u,loy,abt,a,j,i;
112     scanf( " %d ",&t);
113      while(t--)
114     {
115         scanf( " %d%d ",&n,&m);
116         init();
117 
118          for( i =  1 ; i < n;++i)
119         {
120             scanf( " %d%d%d ",&u,&loy,&abt);
121             g[u].push_back(i);
122             sta[i].loy = loy;
123             sta[i].abt = abt ;
124             sta[i].id = i;
125             map1[loy] = i;
126 
127         }
128 
129         dfs( 0);
130 
131         build( 1, 0,num -  1);
132         sort(sta +  1,sta + n,cmp); // 排序为了下面 查询 打基础,排好序之后,我们插入时,保证了,比 i 大的已经插入了这时直接找,忠诚的uida就可以了
133 
134 
135          for( i =  1 ; i < n ;i = j)
136         {
137                j = i;
138 
139              while(j < n &&sta[i].abt == sta[j].abt)
140             {
141                  int id = sta[j].id ;
142                 loy =  get( 1,l[id] +  1,r[id] -  1);
143 
144                  if(loy != - 1) ans[id] = map1[loy] ;
145                  else ans[id] = - 1;
146 
147                 ++j;
148 
149             }
150 
151                   j = i ;
152              while(j < n && sta[i].abt == sta[j].abt )
153             {
154                  int id =  sta[j].id;
155                 insert( 1,l[id],sta[j].loy);
156                 ++j;
157             }
158 
159 
160 
161         }
162          while(m--)
163         {
164             scanf( " %d ",&a);
165 
166             printf( " %d\n ",ans[a]) ;
167         }
168     }
169 
170 }

 

 


 

 

转载于:https://www.cnblogs.com/acSzz/archive/2012/08/17/2643410.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值