Successor HDU - 4366 分块
代码+注释:
1 /*
2 题意:
3 一共有n个人,其中0号是总裁(金字塔顶尖)。后面输入其他n-1个人的信息啊a、b、c,分别代表第i个人的上级是a,他的
4 忠诚度为b,他的能力为c。后面有m次询问。他问你能不能找到一个能力比他高的,且忠诚度最高的人。(注意能力只需要
5 大于此人就可以,不需要最高)
6
7
8 题解:
9 这道题目用的是分块的方法
10
11 首先需要跑一遍dfs来确定每一个人所处于金字塔的位置。从总裁开始向他的下属跑dfs(注意是dfs不是bfs)
12 因为这样我们最后会得到一个pre数组和一个last数组。这两个数组的作用就是来看某个人x他在金字塔中的位置
13 以及他的下属最大的位置(这个位置的值是cnt)。那么pre[x]到last[x]之间的所有人都是x的下属
14
15 然后分块也是按照位置的编号进行分块的,这个样子维护也好维护。分块后会得到一个maxx数组,这个数组的作用就是
16 maxx[x][y]:在第x个块里,能力大于y且忠诚度最高的值,这个p[x][y]存放的是这个值所对应的人
17
18 id数组里面放的是就是,id[x]表示:位置为x的人的在输入中的编号是多少
19
20 具体看代码
21 */
22 #include<stdio.h>
23 #include<string.h>
24 #include<iostream>
25 #include<algorithm>
26 #include<math.h>
27 #include<vector>
28 using namespace std;
29 const int maxn=50005;
30 const int maxm=sqrt(50000)+5;
31 int n,m,block,num;
32 int belong[maxn],l[maxn],r[maxn],last[maxn],cnt=0,pre[maxn];
33 int id[maxn],v[maxn],a[maxn],maxx[maxm][maxm],p[maxm][maxm];
34 struct node
35 {
36 int ability,loyalty,id;
37 node(int l=0,int a=0,int id=0):loyalty(l),ability(a),id(id) {};
38 bool operator <(const node& r)const
39 {
40 return ability<r.ability;
41 }
42 } c[maxn];
43 vector<node>b[maxn];
44 vector<int>g[maxn];
45 void build()
46 {
47 block = sqrt(n);
48 num = n / block;
49 if(n % block) num++;
50 for(int i = 1; i <= num; i++)
51 {
52 l[i] = (i-1)*block+1;
53 r[i] = i*block;
54 }
55 r[num] = n;
56 for(int i = 1; i <= n; i++)
57 {
58 belong[i] = (i-1)/block+1;
59 }
60 for(int i = 1; i <= num; i++)
61 {
62 for(int j = l[i]; j <= r[i]; j++)
63 {
64 int idd = id[j];
65 c[j] = node(v[idd], a[idd], idd);
66 b[i].push_back(node(v[idd], a[idd], idd));
67 }
68 sort(b[i].begin(), b[i].end());
69 int len = b[i].size();
70 maxx[i][len] = -1;
71 for(int j = len-1; j >= 0; j--)
72 {
73 if(maxx[i][j+1] < b[i][j].loyalty)
74 {
75 maxx[i][j] = b[i][j].loyalty;
76 p[i][j] = b[i][j].id;
77 }
78 else
79 {
80 maxx[i][j] = maxx[i][j+1];
81 p[i][j] = p[i][j+1];
82 }
83 }
84 }
85 }
86 int query(int fa,int x,int y)
87 {
88 int ans=-1,id=-1;
89 if(belong[x]==belong[y])
90 {
91 for(int i=x; i<=y; ++i)
92 {
93 if(a[fa]<c[i].ability && ans<c[i].loyalty)
94 {
95 ans=c[i].loyalty;
96 id=c[i].id;
97 }
98 }
99 }
100 else
101 {
102 for(int i=x; i<=r[belong[x]]; ++i)
103 {
104 if(a[fa]<c[i].ability && ans<c[i].loyalty)
105 {
106 ans=c[i].loyalty;
107 id=c[i].id;
108 }
109 }
110
111 for(int i=belong[x]+1; i<belong[y]; ++i)
112 {
113 int pos = upper_bound(b[i].begin(), b[i].end(), node(0, a[fa], 0)) - b[i].begin();
114 int cur = maxx[i][pos];
115 if(ans < cur)
116 {
117 ans = cur;
118 id = p[i][pos];
119 }
120 }
121
122 for(int i=l[belong[y]]; i<=y; ++i)
123 {
124 if(a[fa]<c[i].ability && ans<c[i].loyalty)
125 {
126 ans=c[i].loyalty;
127 id=c[i].id;
128 }
129 }
130 }
131 return id;
132 }
133 void init()
134 {
135 for(int i=0; i<=n; ++i)
136 {
137 b[i].clear();
138 g[i].clear();
139 }
140 cnt=0;
141 }
142 void dfs(int root,int fa)
143 {
144 pre[root]=++cnt;
145 id[cnt]=root;
146 int len=g[root].size();
147 for(int i=0; i<len; ++i)
148 {
149 int v=g[root][i];
150 if(v!=fa) dfs(v,root);
151 }
152 last[root]=cnt;
153 }
154 int main()
155 {
156 int t;
157 scanf("%d",&t);
158 while(t--)
159 {
160 scanf("%d%d",&n,&m);
161 init();
162 for(int i=1; i<=n-1; ++i)
163 {
164 int x;
165 scanf("%d%d%d",&x,&v[i],&a[i]);
166 g[x].push_back(i);
167 }
168 dfs(0,0);
169 build();
170 while(m--)
171 {
172 int x;
173 scanf("%d",&x);
174 printf("%d\n",query(x,pre[x],last[x]));
175 }
176 }
177 return 0;
178 }
Successor HDU - 4366 分块的更多相关文章
- Successor HDU - 4366 (预处理,线段树,dfs序)
Successor HDU - 4366 Sean owns a company and he is the BOSS.The other Staff has one Superior.every s ...
- Successor hdu 4366 线段树
题意: 现在n个人,其中编号0的是老板,之后n-1个员工,每个员工只有一个上司,有一个忠诚值和能力值.每次要解雇一个人的时候,从他的下属中选取能力值大于他的且忠诚值最高的一个,若不存在则输出-1.共m ...
- HDU - 4366 Successor DFS区间+线段树
Successor:http://acm.hdu.edu.cn/showproblem.php?pid=4366 参考:https://blog.csdn.net/colin_27/article/d ...
- HDU 5213 分块 容斥
给出n个数,给出m个询问,询问 区间[l,r] [u,v],在两个区间内分别取一个数,两个的和为k的对数数量. $k<=2*N$,$n <= 30000$ 发现可以容斥简化一个询问.一个询 ...
- HDU 5145 分块 莫队
给定n个数,q个询问[l,r]区间,每次询问该区间的全排列多少种. 数值都是30000规模 首先考虑计算全排列,由于有同种元素存在,相当于每次在len=r-l+1长度的空格随意放入某种元素即$\bin ...
- HDU 2920 分块底数优化 暴力
其实和昨天写的那道水题是一样的,注意爆LL $1<=n,k<=1e9$,$\sum\limits_{i=1}^{n}(k \mod i) = nk - \sum\limits_{i=1}^ ...
- hdu 4366 Successor - CDQ分治 - 线段树 - 树分块
Sean owns a company and he is the BOSS.The other Staff has one Superior.every staff has a loyalty an ...
- HDU 4366 Successor 分块做法
http://acm.hdu.edu.cn/showproblem.php?pid=4366 今日重新做了这题的分块,果然是隔太久了,都忘记了.. 首先,用DFS序变成一维的问题 关键是它有两个权值, ...
- HDU 4366 Successor(dfs序 + 分块)题解
题意:每个人都有一个上司,每个人都有能力值和忠诚值,0是老板,现在给出m个询问,每次询问给出一个x,要求你找到x的所有直系和非直系下属中能力比他高的最忠诚的人是谁 思路:因为树上查询很麻烦,所以我们直 ...
随机推荐
- 【Problems】端口被占用 查看是被谁占用并关闭它
文章目录 Windows Linux 经常在Windows.Linux环境下运行JavaWeb项目,Tomcat的端口被占用了. 端口被占用就查看是被谁占用关闭它就行. Windows 在Window ...
- 深入理解Redis之简单动态字符串
目录 SDS SDS与C字符串的区别 SDS获取字符串长度复杂度为O(1),C字符串为O(N) SDS杜绝了缓存区溢出 减少修改字符串时带来的内存重分配次数 二进制安全 Redis没有直接使用C语言传 ...
- SDUST数据结构 - chap5 数组与广义表
选择题:
- 【葵花宝典】一天掌握Kubernetes
1.kubernetes介绍 kubernetes,简称K8s,是用8代替8个字符"ubernete"而成的缩写.是一个开源的,用于管理云平台中多个主机上的容器化的应用,Kuber ...
- SAP IDES登陆的short dump终于不见了
还记得这个IDES登陆的shortdump吗今天对内核从701_rel 升级到721,发现登陆的错误没了,看来721_rel内核支持的操作系统和数据库更多了,兼容性也更好了.
- 镍氢可充电电池2.4V转3.3V,2V转3.3V稳压供电输出电路图
PW5100可以实现2.4V转3.3V,2V转3.3V的稳压电源电路,输出电流500MA.静态电流10uA,SOT23-5封装.输出纹波低,轻载性能高(轻载电感推荐6.8UH-10UH). PW510 ...
- javascript判断浏览器访问,刷新,返回
话不多说,直接上 if (window.performance.navigation.type === 0/* 正常访问 */) { // 你要干的事 } else if (window.perfor ...
- 【pytest】(十二)参数化测试用例中的setup和teardown要怎么写?
还是一篇关于pytest的fixture在实际使用场景的分享. fixture我用来最多的就是写setup跟teardown了,那么现在有一个用例是测试一个列表接口,参数化了不同的状态值传参,来进行测 ...
- 订单业务楼层化 view管理器和model管理器进行了model和view的全面封装处理 三端不得不在每个业务入口上线时约定好降级开关,于是代码中充满了各种各样的降级开关字段
京东APP订单业务楼层化技术实践解密 原创 杜丹 留成 博侃 京东零售技术 2020-09-29 https://mp.weixin.qq.com/s/2oExMjh70Kyveiwh8wOBVA 用 ...
- 小鹏汽车技术中台实践 :微服务篇 InfoQ 今天 以下文章来源于InfoQ Pro
小鹏汽车技术中台实践 :微服务篇 InfoQ 今天 以下文章来源于InfoQ Pro