HDU 4366 Successor 分块做法
http://acm.hdu.edu.cn/showproblem.php?pid=4366
今日重新做了这题的分块,果然是隔太久了,都忘记了。。
首先,用DFS序变成一维的问题
关键是它有两个权值,该如何处理呢?
首先假设我们的DFS序列是List,
那么,对其进行分块。对于每一个块,先按能力排序,用数组tosort[]保存,这样我就可以用O(magic)的时间,就是扫一次这个块,维护出一个数组,mx[i]表示大于等于tosort[i].ablity时,最大的忠诚度。
那么我查询的时候,就可以,如果不在块里的,暴力,否则,因为每一个块已经排好序,那么我可以二分出一个位置,找到第一个能力值大于等于所查询的val,那么mx[pos]是答案,因为mx[pos]就表示大于等于这个位置的能力值,所拥有的最大忠诚度。
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
const int maxn = + ;
struct Edge {
int u, v, w;
int tonext;
}e[ * maxn];
int num;
int first[maxn + ];
int getid[ + ];
struct node {
int loy, abi;
bool operator < (const struct node & rhs) const {
return abi < rhs.abi;
}
}a[maxn], List[maxn], tosort[maxn];
void addEgde(int u, int v) {
++num;
e[num].u = u;
e[num].v = v;
e[num].tonext = first[u];
first[u] = num;
}
int DFN;
int L[maxn], R[maxn];
bool vis[maxn];
void dfs(int cur) {
L[cur] = DFN;
for (int i = first[cur]; i; i = e[i].tonext) {
int v = e[i].v;
// assert(vis[v] == false);
// vis[v] = true;
++DFN;
List[DFN] = tosort[DFN] = a[v];
dfs(v);
}
R[cur] = DFN;
}
int magic;
int mx[maxn];
int tofind(int begin, int end, int val) {
// cout << begin << " " << end << " ***" << endl;
if (tosort[end].abi <= val) return -;
if (tosort[begin].abi > val) return mx[begin];
while (begin <= end) {
int mid = (begin + end) >> ;
if (tosort[mid].abi > val) {
end = mid - ;
} else begin = mid + ;
}
return mx[begin];
}
void work() {
int n, m;
cin >> n >> m;
magic = (int)sqrt(n * 1.0);
for (int i = ; i <= n - ; ++i) {
int fa;
cin >> fa >> a[i].loy >> a[i].abi;
getid[a[i].loy] = i;
addEgde(fa, i);
}
dfs();
// for (int i = 0; i <= n - 1; ++i) {
// cout << L[i] << " " << R[i] << endl;
// }
for (int i = ; i < n; i += magic) {
int j = i + magic;
if (j > n) break;
sort(tosort + i, tosort + j);
mx[j - ] = tosort[j - ].loy;
for (int k = j - ; k >= i; --k) {
if (tosort[k].loy < mx[k + ]) {
mx[k] = mx[k + ];
} else mx[k] = tosort[k].loy;
}
// for (int k = i; k < i + magic; ++k) {
// cout << mx[k] << endl;
// }
}
while (m--) {
int id;
cin >> id;
int val = a[id].abi;
int begin = L[id], end = R[id];
// cout << begin << " " << end << " ***" << endl;
int ans = -;
for (int i = begin + ; i <= end;) {
if (i % magic == && i + magic <= end) {
ans = max(ans, tofind(i, i + magic - , val));
i += magic;
} else {
if (List[i].abi > val && ans < List[i].loy) {
ans = List[i].loy;
}
++i;
}
}
if (ans == -) {
cout << - << endl;
} else cout << getid[ans] << endl;
}
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
IOS;
a[].abi = a[].loy = -;
List[] = tosort[] = a[];
int t;
cin >> t;
while (t--) {
DFN = ;
num = ;
memset(mx, -, sizeof mx);
memset(first, , sizeof first);
work();
}
return ;
}
这题可以用线段树做。
对于这一类题目,就是要维护的东西有两个的。
1、能力值要比所查询的元素大
2、要在一定的区间里查询这些值。
有一个很好用的方法就是排序。
我们肯定是要排除一个因数的影响的了。
我们可以按能力排序,然后先查询能力值最大的(肯定是-1)
然后把它插进线段树,然后找次大的。
这样就确保了每个元素查询的,都是合法的(就是里面的元素,能力值都比他大)
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL; #include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#define lson L, mid, cur << 1
#define rson mid + 1, R, cur << 1 | 1
const int maxn = + ;
struct Edge {
int u, v, w;
int tonext;
}e[ * maxn];
int num;
int first[maxn + ];
int getid[ + ];
struct node {
int loy, abi, id;
bool operator < (const struct node & rhs) const {
if (abi != rhs.abi) return abi > rhs.abi;
else return id < rhs.id;
}
}a[maxn], List[maxn], tosort[maxn];
void addEgde(int u, int v) {
++num;
e[num].u = u;
e[num].v = v;
e[num].tonext = first[u];
first[u] = num;
}
int DFN;
int LQ[maxn], RQ[maxn];
void dfs(int cur) {
LQ[cur] = DFN;
for (int i = first[cur]; i; i = e[i].tonext) {
int v = e[i].v;
++DFN;
List[DFN] = tosort[DFN] = a[v];
dfs(v);
}
RQ[cur] = DFN;
}
int mx[maxn << ];
void pushUp(int cur) {
mx[cur] = max(mx[cur << ], mx[cur << | ]);
}
void UpDate(int pos, int val, int L, int R, int cur) {
if (L == R) {
if (pos == L) {
mx[cur] = val; //wa
}
return;
}
int mid = (L + R) >> ;
if (pos <= mid) UpDate(pos, val, lson);
else UpDate(pos, val, rson);
pushUp(cur);
}
int query(int begin, int end, int L, int R, int cur) {
if (L >= begin && R <= end) {
return mx[cur];
}
int mid = (L + R) >> ;
int lans = -inf, rans = -inf;
if (mid < end) rans = query(begin, end, rson);
if (mid >= begin) lans = query(begin, end, lson);
return max(lans, rans);
}
int ans[maxn];
void work() {
int n, m;
cin >> n >> m;
for (int i = ; i <= n - ; ++i) {
int fa;
cin >> fa >> a[i].loy >> a[i].abi;
a[i].id = i;
getid[a[i].loy] = i;
addEgde(fa, i);
}
dfs();
sort(a, a + n);
memset(mx, -, sizeof mx);
for (int i = ; i < n; ++i) {
int id;
if (i == n - ) id = ;
else id = getid[a[i].loy];
int res = query(LQ[id], RQ[id], , n - , );
if (res == -) ans[id] = -;
else ans[id] = getid[res];
UpDate(LQ[id], a[i].loy, , n - , );
}
for (int i = ; i <= m; ++i) {
int id;
cin >> id;
cout << ans[id] << endl;
}
} int main() {
#ifdef local
freopen("data.txt", "r", stdin);
// freopen("data.txt", "w", stdout);
#endif
IOS; int t;
cin >> t;
while (t--) {
a[].abi = a[].loy = -inf;
a[].id = ;
DFN = ;
num = ;
memset(first, , sizeof first);
work();
}
return ;
}
HDU 4366 Successor 分块做法的更多相关文章
- HDU - 4366 Successor DFS区间+线段树
Successor:http://acm.hdu.edu.cn/showproblem.php?pid=4366 参考:https://blog.csdn.net/colin_27/article/d ...
- 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(dfs序 + 分块)题解
题意:每个人都有一个上司,每个人都有能力值和忠诚值,0是老板,现在给出m个询问,每次询问给出一个x,要求你找到x的所有直系和非直系下属中能力比他高的最忠诚的人是谁 思路:因为树上查询很麻烦,所以我们直 ...
- HDU - 4366 Successor DFS序 + 分块暴力 or 线段树维护
给定一颗树,每个节点都有忠诚和能力两个参数,随意指定一个节点,要求在它的子树中找一个节点代替它,这个节点要满足能力值大于它,而且是忠诚度最高的那个. 首先,dfs一下,处理出L[i], R[i]表示d ...
- HDU 4366 Successor
Successor Time Limit: 1000ms Memory Limit: 65536KB This problem will be judged on HDU. Original ID: ...
- HDU 4366 Successor(树链剖分+zkw线段树+扫描线)
[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=4366 [题目大意] 有一个公司,每个员工都有一个上司,所有的人呈树状关系,现在给出每个人的忠诚值和 ...
- HDU 4366 Successor( DFS序+ 线段树 )
Successor Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total S ...
- 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 分块
代码+注释: 1 /* 2 题意: 3 一共有n个人,其中0号是总裁(金字塔顶尖).后面输入其他n-1个人的信息啊a.b.c,分别代表第i个人的上级是a,他的 4 忠诚度为b,他的能力为c.后面有m次 ...
随机推荐
- 正则工具类以及FinalClass
版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/jadyer/article/details/27811103 完整版见https://jadyer. ...
- js中字符串函数indexOf与search的区别
IndexOf()方法是用来判断一个字符串是否存在于一个更长的字符串中.从长字符串左端到右端来搜索,如果存在该子字符串就返回它所处的位置(即索引).如果在被搜索的字符串没有找到要查找的字符串返回-1. ...
- ReactMotion Demo8 分析
链接 首先通过spring函数Motion的style参数, 传入Motion Component, 计算style的过程: const style = lastPressed === i & ...
- 初探linux子系统集之led子系统(三)【转】
本文转载自:http://blog.csdn.net/eastmoon502136/article/details/37822837 世界杯结束了,德国战车夺得了大力神杯,阿根廷最终还是失败了.也许3 ...
- RedisCluster集群搭建
搭建集群方案 安装部署任何一个应用其实都很简单,只要安装步骤一步一步来就行了.下面说一下 Redis 集群搭建规划,由于集群至少需要6个节点(3主3从模式),所以,没有这么多机器给我玩,我本地也起不了 ...
- 项目中Redis分库
Redis中有16个库 默认第0个库 配置库的设置: 不同的库 key可以重复哈 公司的多个不同分布式项目,但是只有一个redis时候,以项目方式区分不同的库 每个项目连接相同 但是库不同
- YTU 2802: 判断字符串是否为回文
2802: 判断字符串是否为回文 时间限制: 1 Sec 内存限制: 128 MB 提交: 348 解决: 246 题目描述 编写程序,判断输入的一个字符串是否为回文.若是则输出"Yes ...
- YTU 2424: C语言习题 字符串比较
2424: C语言习题 字符串比较 时间限制: 1 Sec 内存限制: 128 MB 提交: 1042 解决: 613 题目描述 写一函数,实现两个字符串的比较.即自己写一个strcmp函数,函数 ...
- 织梦CMS使用JS实时动态调用评论数
网站中只要启用了会员系统,网站中的文章就会有评论,在网站首页中调用会员评论也能提升会员体验度,网页都是静态页面,如果每有一个评论都更新html的话就会有点浪费资源了,所以这里给大家分享一个使用JS调用 ...
- 「LuoguT36048」 Storm in Lover
Description 平成二十四年(2012年),5月11日,东京,某弓道场. "呐,呐,海未酱,你听说了吗?几天后的那场弓道大会?啊-!"橙发少女兴奋地拿着一张传单一样的纸跑向 ...