hdu4366 线段树:dfs序将树型转化为线型
求一个点的下属中能力比自己高,且在所有下属中忠诚度最高的点。
dfs扫出左端点右端点,然后按照能力从大到小,id从小到大排序。
然后简单的线段树单点修改(忠诚值),区间查询最大(忠诚值)。
1 #include<stdio.h> 2 #include<string.h> 3 #include<map> 4 #include<algorithm> 5 using namespace std; 6 map<int,int>f; 7 struct dian{ 8 int n,z,id; 9 }a[200005]; 10 int time_,now,head[200005],next[200005],point[200005]; 11 int ll[200005],rr[200005],maxv[300005],ans[200005]; 12 int cmp(dian n1,dian n2) 13 { 14 if (n1.n>n2.n) return 1; 15 if (n1.n==n2.n&&n1.id<n2.id) return 1; 16 return 0; 17 } 18 void add(int u,int v) 19 { 20 next[++now]=head[u]; 21 head[u]=now; 22 point[now]=v; 23 } 24 void dfs(int pre,int u) 25 { 26 ll[u]=++time_; 27 for (int i=head[u];i!=-1;i=next[i]) 28 { 29 int v=point[i]; 30 if (v==pre) continue; 31 dfs(u,v); 32 } 33 rr[u]=time_; 34 } 35 int query(int o,int l,int r,int ql,int qr) 36 { 37 int tmp=-1,mid=l+(r-l)/2; 38 if (ql<=l&&qr>=r) return maxv[o]; 39 if (ql<=mid) tmp=max(tmp,query(o*2,l,mid,ql,qr)); 40 if (qr>mid) tmp=max(tmp,query(o*2+1,mid+1,r,ql,qr)); 41 return tmp; 42 } 43 void update(int o,int l,int r,int p,int v) 44 { 45 int mid=l+(r-l)/2; 46 if (l==r) {maxv[o]=v; return; } 47 if (p<=mid) update(o*2,l,mid,p,v); 48 if (p>mid) update(o*2+1,mid+1,r,p,v); 49 maxv[o]=max(maxv[o*2],maxv[o*2+1]); 50 } 51 int main() 52 { 53 int T,n,m,i,x; 54 scanf("%d",&T); 55 while (T--) 56 { 57 scanf("%d%d",&n,&m); 58 memset(head,-1,sizeof(head)); 59 now=time_=0; 60 for (i=1;i<n;i++) 61 { 62 scanf("%d%d%d",&x,&a[i].z,&a[i].n); 63 a[i].id=i; f[a[i].z]=i; 64 add(i,x); add(x,i); 65 } 66 dfs(-1,0); 67 memset(maxv,-1,sizeof(maxv)); 68 memset(ans,-1,sizeof(ans)); 69 sort(a+1,a+n,cmp); 70 for (i=1;i<n;i++) 71 { 72 ans[a[i].id]=query(1,1,n,ll[a[i].id],rr[a[i].id]); 73 update(1,1,n,ll[a[i].id],a[i].z); 74 } 75 while (m--) 76 { 77 scanf("%d",&x); 78 printf("%d\n",ans[x]==-1?-1:f[ans[x]]); 79 } 80 } 81 return 0; 82 }