HDOJ4366解题报告【dfs序+线段树】
题目地址:
http://acm.hdu.edu.cn/showproblem.php?pid=4366
题目概述:
给出一个公司所有员工的上下级关系(数据保证是一棵树),现在想解雇一些员工,而他们的位置由他们的手下里能力值比他大而且忠诚度最高的人来替代,给出m个询问,求输出替代他们的人的编号。
大致思路:
学习了一下dfs序的用法,附学习的博客:http://blog.csdn.net/Miracle_ma/article/details/51485118
简单的说dfs序就是将一棵树变成线性结构的算法,并且保证点i的子树都在i的后面。
根据dfs序首先将员工之间的关系转化成数组,然后对于员工的数据a按照能力值降序排列,并且将所有的询问q也按对应的能力值降序排列。
排完序之后依次插入a中的元素进入线段树中,比较当前插入的ai与未处理的q中能力值最高的比较,如果ai的能力值比较小,则处理这个询问,否则继续插入。
代码:
1 #include <iostream> 2 #include <cstdio> 3 #include <cstdlib> 4 #include <cmath> 5 #include <vector> 6 #include <ctime> 7 #include <map> 8 #include <stack> 9 #include <queue> 10 #include <cstring> 11 #include <algorithm> 12 using namespace std; 13 14 #define sacnf scanf 15 #define scnaf scanf 16 #define maxn 50010 17 #define maxm 26 18 #define inf 1061109567 19 #define Eps 0.00001 20 const double PI=acos(-1.0); 21 #define mod 7 22 #define MAXNUM 10000 23 void Swap(int &a,int &b) {int t=a;a=b;b=t;} 24 int Abs(int x) {return (x<0)?-x:x;} 25 typedef long long ll; 26 typedef unsigned int uint; 27 28 struct node 29 { 30 int pos,abi,loy; 31 bool operator < (const node &a) const 32 { 33 if(abi==a.abi) return loy>a.loy; 34 return abi>a.abi; 35 } 36 } a[maxn]; 37 38 struct node1 39 { 40 int pos,val; 41 } q[maxn]; 42 43 vector<int> G[maxn]; 44 int tme; 45 int st[maxn],ed[maxn]; 46 int tabi[maxn],tloy[maxn]; 47 int ans[maxn]; 48 int tree[maxn*4]; ///loy最大的点的编号 49 50 bool cmp(node1 a,node1 b) 51 { 52 return tabi[a.val]>tabi[b.val]; 53 } 54 55 void dfs(int u,int fa) 56 { 57 st[u]=++tme; 58 int len=G[u].size(); 59 for(int i=0;i<len;i++) 60 { 61 int v=G[u][i]; 62 if(v!=fa) dfs(v,u); 63 } 64 ed[u]=tme; 65 } 66 67 void build_tree(int l,int r,int dir) 68 { 69 if(l==r) 70 { 71 tree[dir]=1; 72 return; 73 } 74 int m=(l+r)>>1; 75 build_tree(l,m,dir<<1); 76 build_tree(m+1,r,dir<<1|1); 77 tree[dir]=1; 78 } 79 80 void add(int l,int r,int dir,int pos,int val) 81 { 82 if(l==r) 83 { 84 tree[dir]=(tloy[tree[dir]]<tloy[val])?val:tree[dir]; 85 return; 86 } 87 int m=(l+r)>>1; 88 if(pos<=m) add(l,m,dir*2,pos,val); 89 else add(m+1,r,dir*2+1,pos,val); 90 tree[dir]=(tloy[tree[dir*2]]<tloy[tree[dir*2+1]])?tree[dir*2+1]:tree[dir*2]; 91 } 92 93 int query(int l,int r,int dir,int ql,int qr) 94 { 95 if(ql>qr) return 1; 96 if(ql>r||l>qr) return 1; 97 if(ql<=l&&r<=qr) return tree[dir]; 98 int m=(l+r)>>1,t1,t2; 99 t1=query(l,m,dir<<1,ql,qr); 100 t2=query(m+1,r,dir<<1|1,ql,qr); 101 return (tloy[t1]<tloy[t2])?t2:t1; 102 } 103 104 int main() 105 { 106 //freopen("data.in","r",stdin); 107 //freopen("data.out","w",stdout); 108 //clock_t st=clock(); 109 int n,m,T;scanf("%d",&T);tree[0]=-1; 110 while(T--) 111 { 112 sacnf("%d%d",&n,&m); 113 int x; 114 115 a[1].pos=1;a[1].abi=a[1].loy=-1; 116 tloy[1]=tabi[1]=-1; 117 for(int i=1;i<=n;i++) G[i].clear(); 118 119 for(int i=2;i<=n;i++) 120 { 121 scanf("%d%d%d",&x,&a[i].loy,&a[i].abi); 122 x++;a[i].pos=i;tabi[i]=a[i].abi;tloy[i]=a[i].loy; 123 G[x].push_back(i);G[i].push_back(x); 124 } 125 126 tme=0; 127 dfs(1,-1); 128 build_tree(1,n,1); 129 130 sort(a+1,a+1+n); ///按ability降序排列 a-->第i个人的数据 131 132 for(int i=1;i<=m;i++) ///q-->第i个询问的序号及询问编号 133 { 134 scanf("%d",&q[i].val);q[i].val++; 135 q[i].pos=i; 136 } 137 sort(q+1,q+1+m,cmp); ///按ability降序排列 138 139 int i=1,j=1; 140 while(i<=m) 141 { 142 int p=a[j].pos; 143 if(a[j].abi<=tabi[q[i].val]) 144 { 145 int temp=query(1,n,1,st[q[i].val]+1,ed[q[i].val]); 146 ans[q[i].pos]=temp-1;i++; 147 if(i>m) break; 148 } 149 else if(j<n) 150 { 151 add(1,n,1,st[p],p);j++; 152 } 153 } 154 for(i=1;i<=m;i++) printf("%d\n",(ans[i]==0)?-1:ans[i]); 155 } 156 //clock_t ed=clock(); 157 //printf("\n\nTime Used : %.5lf Ms.\n",(double)(ed-st)/CLOCKS_PER_SEC); 158 return 0; 159 }