HDU4366 Successor

题意:

给出一棵根为\(1\)的树,每个点有两个权值\(x,y\),每次询问一个点的子树中\(x\)比这个点的\(x\)大且\(y\)值最大的那个点

题解:

如果以dfs序来看的话,每个点的子树可以看作是dfs序的一段区间

然后我们对这个序列分块,每个块内按\(x\)排序,然后维护后缀\(y\)的最大值

每次查询的时候对于一个块,可以先二分出来符合条件的\(x\)最小的那个位置,然后找后缀\(y\)最大的那个点

如果要单点修改的话,每次对一个块暴力修改也是没有问题的


//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 5e4+7;
int T,n,m,q;
vector<int> G[MAXN];
int st[MAXN],ed[MAXN],belong[MAXN],l[MAXN],r[MAXN],sqt;
pair<int,int> emp[MAXN];
vector<int> ord;
void dfs(int u){
st[u] = ord.size();
ord.push_back(u);
for(int v : G[u]) dfs(v);
ed[u] = ord.size() - 1;
}
void divide(){
sqt = sqrt(n);
m = n / sqt + (n%sqt==0?0:1);
for(int i = 0; i < n; i++) belong[i] = i / sqt + 1;
for(int i = 1; i <= m; i++) l[i] = sqt * (i-1), r[i] = sqt * i - 1;
r[m] = n - 1;
}
vector<pair<pair<int,int>,int>> vec[MAXN];
vector<pair<int,int>> suf[MAXN];
void build(){
for(int i = 1; i <= m; i++){
vec[i].clear(); suf[i].clear();
for(int j = l[i]; j <= r[i]; j++) vec[i].emplace_back(make_pair(emp[ord[j]],ord[j]));
sort(vec[i].begin(),vec[i].end());
suf[i].resize(vec[i].size());
suf[i].back() = make_pair(vec[i].back().first.second,vec[i].back().second);
for(int j = ((int)suf[i].size()) - 2; j >= 0; j--){
if(vec[i][j].first.second>suf[i][j+1].first) suf[i][j] = make_pair(vec[i][j].first.second,vec[i][j].second);
else suf[i][j] = suf[i][j+1];
}
}
}
void ask(){
int x;
scanf("%d",&x); x++;
int L = st[x], R = ed[x];
x = emp[x].first;
int lp = belong[L], rp = belong[R];
int res = -1;
if(lp==rp){
for(int i = L; i <= R; i++){
if(emp[ord[i]].first<=x) continue;
if(res==-1) res = ord[i];
else if(emp[ord[i]].second>emp[res].second) res = ord[i];
}
}
else{
for(int i = L; i <= r[lp]; i++){
if(emp[ord[i]].first<=x) continue;
if(res==-1) res = ord[i];
else if(emp[ord[i]].second>emp[res].second) res = ord[i];
}
for(int i = l[rp]; i <= R; i++){
if(emp[ord[i]].first<=x) continue;
if(res==-1) res = ord[i];
else if(emp[ord[i]].second>emp[res].second) res = ord[i];
}
lp++, rp--;
for(int i = lp; i <= rp; i++){
auto p = lower_bound(vec[i].begin(),vec[i].end(),make_pair(make_pair(x+1,0),1));
if(p==vec[i].end()) continue;
int pt = p - vec[i].begin();
if(res==-1 or suf[i][pt].first>emp[res].second) res = suf[i][pt].second;
}
}
printf("%d\n",res==-1?-1:res-1);
}
void solve(){
scanf("%d %d",&n,&q);
for(int i = 1; i <= n; i++) G[i].clear();
for(int i = 2; i <= n; i++){
int x;
scanf("%d %d %d",&x,&emp[i].second,&emp[i].first);
G[++x].push_back(i);
}
ord.clear();
dfs(1);
divide();
build();
while(q--) ask();
}
int main(){
for(scanf("%d",&T); T; T--) solve();
return 0;
}

HDU4366 Successor【dfs序 分块】的更多相关文章

  1. HDU - 4366 Successor DFS序 + 分块暴力 or 线段树维护

    给定一颗树,每个节点都有忠诚和能力两个参数,随意指定一个节点,要求在它的子树中找一个节点代替它,这个节点要满足能力值大于它,而且是忠诚度最高的那个. 首先,dfs一下,处理出L[i], R[i]表示d ...

  2. 【HDU4366】【DFS序+分块】Successor

    Problem Description Sean owns a company and he is the BOSS.The other Staff has one Superior.every st ...

  3. HDU 4366 Successor(dfs序 + 分块)题解

    题意:每个人都有一个上司,每个人都有能力值和忠诚值,0是老板,现在给出m个询问,每次询问给出一个x,要求你找到x的所有直系和非直系下属中能力比他高的最忠诚的人是谁 思路:因为树上查询很麻烦,所以我们直 ...

  4. 2016 ACM/ICPC Asia Regional Dalian Online 1010 Weak Pair dfs序+分块

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submissio ...

  5. BZOJ4867 Ynoi2017舌尖上的由乃(dfs序+分块)

    容易想到用dfs序转化为序列上的问题.考虑分块,对每块排序,修改时对于整块打上标记,边界暴力重构排序数组,询问时二分答案,这样k=sqrt(nlogn)时取最优复杂度nsqrt(nlogn)logn, ...

  6. BZOJ 4765 普通计算姬 dfs序+分块+树状数组+好题!!!

    真是道好题...感到灵魂的升华... 按dfs序建树状数组,拿前缀和去求解散块: 按点的标号分块,分成一个个区间,记录区间子树和 的 总和... 具体地,需要记录每个点u修改后,对每一个块i的贡献,记 ...

  7. bzoj 4765 普通计算姬 dfs序 + 分块

    题目链接 Description "奋战三星期,造台计算机".小G响应号召,花了三小时造了台普通计算姬.普通计算姬比普通计算机要厉害一些.普通计算机能计算数列区间和,而普通计算姬能 ...

  8. HDU 4366 Successor( DFS序+ 线段树 )

    Successor Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total S ...

  9. 2018.06.30 BZOJ4765: 普通计算姬(dfs序+分块+树状数组)

    4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MB Description "奋战三星期,造台计算机".小G响应号召,花了三小时 ...

随机推荐

  1. Spring Boot 计划任务中的一个“坑”

    计划任务功能在应用程序及其常见,使用Spring Boot的@Scheduled 注解可以很方便的定义一个计划任务.然而在实际开发过程当中还应该注意它的计划任务默认是放在容量为1个线程的线程池中执行, ...

  2. 剑指offer 面试题10.1:青蛙跳台阶

    题目描述 一只青蛙一次可以跳上1级台阶,也可以跳上2级.求该青蛙跳上一个n级的台阶总共有多少种跳法(先后次序不同算不同的结果). 编程思想 对于本题,前提只有 一次 1阶或者2阶的跳法.a.如果两种跳 ...

  3. MySQL的索引优化分析(一)

    一.SQL分析 性能下降.SQL慢.执行时间长.等待时间长 查询语句写的差 索引失效关联查询太多join(设计缺陷) 单值索引:在user表中给name属性创建索引,create index idx_ ...

  4. LSTM+CRF进行序列标注

    为什么使用LSTM+CRF进行序列标注 直接使用LSTM进行序列标注时只考虑了输入序列的信息,即单词信息,没有考虑输出信息,即标签信息,这样无法对标签信息进行建模,所以在LSTM的基础上引入一个标签转 ...

  5. 【Azure Redis 缓存】Windows和Linux系统本地安装Redis, 加载dump.rdb中数据以及通过AOF日志文件追加数据

    任务描述 本次集中介绍使用Windows和Linux()搭建本地Redis服务器的步骤,从备份的RDB文件中加载数据,以及如何生成AOF文件和通过AOF文件想已经运行的Redis追加数据. 操作步骤 ...

  6. MySQL进阶:约束,多表设计,多表查询,视图,数据库备份与还原

    MySQL进阶 知识点梳理 一.约束 1. 外键约束 为什么要有外键约束 例如:一个user表,一个orderlist 如果现在想要直接删除id为1的张三,但是orderlist里还有用户id为1的订 ...

  7. OAuth2.0是干什么的?

    OAuth2.0是干什么的? 首先用户有一些数据: 将数据存储在服务器上: 这时候有一个应用要访问数据: 如果这个应用是一个恶意程序呢?所以需要一个检验来判断请求是不是安全的: 如何判断是不是安全的? ...

  8. .NET 中依赖注入组件 Autofac 的性能漫聊

    Autofac 是一款超赞的 .NET IoC 容器 ,在众多性能测评中,它也是表现最优秀的一个.它管理类之间的依赖关系, 从而使 应用在规模及复杂性增长的情况下依然可以轻易地修改.它的实现方式是将常 ...

  9. TCMalloc源码学习(四)(小内存块释放)

    pagemap_和pagemap_cache_ PageHeap有两个map,pagemap_记录某一内存页对应哪一个span,显然可能多页对应一个span,pagemap_cache_记录某一内存页 ...

  10. Vue中双向数据绑定是如何实现的?

    vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变:核心:关于VUE双向数据绑定,其核心是 Ob ...