hdu4366-successor-2012 Multi-University Training Contest 7-1007
2012-08-15 10:03
281 查看
Brief Description:
给出一棵树(人与人之间的上下级关系),每个人有一个忠诚度和能力值,现在老板要解雇某些人,老板想要知道解雇一个人x后,x的下属中能力值>=x的能力值并且忠诚度最高的是谁?
Analysis:
对树进行左右编号,一个节点的左右编号一定是覆盖它的所有子树的左右编号(树问题化为区间问题的常用技术),然后我们考虑用线段树来解决这个问题。先按能力值从大到小排序,然后按这个序进行线段树的更新与查询。
具体做法是枚举到某个节点时,首先查询该节点的子树中忠诚度最高的是谁(查询时保证了查询到的节点的能力值>该节点的能力值,这就是排序的原因),然后将该节点的忠诚度更新入线段树。
这道题的做法是看了标程才会的。
对于标程的体会是:
线段树单点更新最值,区间查询最值是很固定化的操作,所以要准备成模板。
对于排序,标程的处理方式是:弄一个下标数组f[i]=i,然后用cmp函数控制排完序后为能力值递减(对应到下标值),这么写很不“工程”,但是很acm,所以也值得借鉴。
给出一棵树(人与人之间的上下级关系),每个人有一个忠诚度和能力值,现在老板要解雇某些人,老板想要知道解雇一个人x后,x的下属中能力值>=x的能力值并且忠诚度最高的是谁?
Analysis:
对树进行左右编号,一个节点的左右编号一定是覆盖它的所有子树的左右编号(树问题化为区间问题的常用技术),然后我们考虑用线段树来解决这个问题。先按能力值从大到小排序,然后按这个序进行线段树的更新与查询。
具体做法是枚举到某个节点时,首先查询该节点的子树中忠诚度最高的是谁(查询时保证了查询到的节点的能力值>该节点的能力值,这就是排序的原因),然后将该节点的忠诚度更新入线段树。
这道题的做法是看了标程才会的。
对于标程的体会是:
线段树单点更新最值,区间查询最值是很固定化的操作,所以要准备成模板。
对于排序,标程的处理方式是:弄一个下标数组f[i]=i,然后用cmp函数控制排完序后为能力值递减(对应到下标值),这么写很不“工程”,但是很acm,所以也值得借鉴。
#include <iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; const int N = 50005; vector<int>E ; int b ,c ,ret ,L ,R ,k; void get(int x) { int i,j; L[x]=R[x]=++k; for(i=E[x].size()-1;i>=0;i--) { j=E[x][i]; get(j); if(R[x]<R[j])R[x]=R[j]; } } struct P { int l,r,mid,key,pos; }arr[4*N]; void build(int le,int ri,int c) { arr[c].l=le; arr[c].r=ri; arr[c].mid=(le+ri)/2; arr[c].key=arr[c].pos=-1; if(le==ri)return ; build(le,arr[c].mid,c+c); build(arr[c].mid+1,ri,c+c+1); } void insert(int x,int v,int c) { if(v>arr[c].key) { arr[c].key=v; arr[c].pos=x; } if(arr[c].l==arr[c].r)return ; if(L[x]<=arr[c].mid)insert(x,v,c+c); else insert(x,v,c+c+1); } int res,id; // 这就是模板嘛! void find(int le,int ri,int c) { if(res>=arr[c].key)return ; if(le<=arr[c].l&&ri>=arr[c].r) { id=arr[c].pos; res=arr[c].key; return ; } if(le<=arr[c].mid)find(le,ri,c+c); if(ri>arr[c].mid)find(le,ri,c+c+1); } int f ; bool cmp(int x,int y) { if(c[x]==c[y])return x<y; return c[x]>c[y]; } bool use[1000001]; int main() { int n,m,i,T,a; scanf("%d",&T); while(T--) { int flag=0; //for(i=0;i<n;i++)E[i].clear(); scanf("%d%d",&n,&m); memset(use,false,sizeof(use)); for(i=0;i<n;i++)E[i].clear(); for(i=1;i<n;i++) { scanf("%d%d%d",&a,b+i,c+i); if(b[i]<0||b[i]>1000000)flag=1; if(use[b[i]])flag=1; // 有多个b[i] use[b[i]]=true; // b[i]有了 E[a].push_back(i); } k=0; get(0); //if(k!=n)puts("error"); //for(i=0;i<n;i++)printf("i:%d L:%d R:%d \n",i,L[i],R[i]); build(1,k,1); // 以下f[i]首先求编号。 for(i=0;i<n;i++)f[i]=i; sort(f,f+n,cmp); // 按能力值从大到小枚举。。 for(i=0;i<n;i++) { res=id=-1; // 找的是能力值比它大的,并且忠诚度最高的。。 find(L[f[i]],R[f[i]],1); ret[f[i]]=id; insert(f[i],b[f[i]],1); } while(m--) { scanf("%d",&a); if(!a)flag=1; printf("%d\n",ret[a]); } if(flag)puts("error"); } //puts("ook"); return 0; }
相关文章推荐
- 2012 Multi-University Training Contest 5-1007 hdu4345
- 2012 Multi-University Training Contest 4-1007 hdu4337 King Arthur's Knights
- 2012 Multi-University Training Contest 1[hdu4300~4309]
- 2012 Multi-University Training Contest 2
- 2012 Multi-University Training Contest 2
- 2012 Multi-University Training Contest 3
- 2012 Multi-University Training Contest 7
- 2012 Multi-University Training Contest 7-1001 hdu4360 As long as Binbin loves Sangsang
- hdu 4353 Finding Mine (计算几何 2012 Multi-University Training Contest 6 )
- 2015 Multi-University Training Contest 5 1007
- hdu 4941 2014 Multi-University Training Contest 7 1007
- HDU 4342 History repeat itself 2012 Multi-University Training Contest 5
- 2012 Multi-University Training Contest 2
- hdu 4322 Candy(最大费用流)2012 Multi-University Training Contest 3
- hdu4325-Flowers-2012 Multi-University Training Contest 3-题解
- 2012 Multi-University Training Contest 5-1011 hdu4349
- 2012 Multi-University Training Contest 7-1003 hdu4362 Dragon Ball
- 2012 Multi-University Training Contest 8[hdu4370~4379]
- HDU 4349 Xiao Ming's Hope 2012 Multi-University Training Contest 5
- HDU 4322 最大费用最大流 2012 Multi-University Training Contest 3