HDU 4366 浅谈DFS序+线段树
来源:互联网 发布:linux 打包tar 编辑:程序博客网 时间:2024/05/21 10:30
世界真的很大
对于树上的询问要有意识地去想要不要吧树上问题转化成序列问题,就可以用线段树一类的数据结构来维护了
DFS序和树链剖分都是很不错的把树转换为序列问题的方法
看题先:
description
给一个树,树上每个节点都有两个属性:忠诚度和能力,给出若干查询,求每个子树中能力 > 树根能力的点中,忠诚度最高的那个n≤50000数值≤1000000
input
第一行一个整数T,表示数据组数每一组数据第一行两个整数n,m,表示树有n个节点,有m组操作接下来n-1行每行两个整数u,v,表示u,v之间有一条边
output:
对于每一个询问一个整数t表示答案,没有就输出-1
如果不管能力值得话,就相当于在一个数的子树里找一个忠诚度最高的,显然可以用DFS序后加以线段树解决,区间最大值而已
然后考虑怎么解决能力值得问题
仔细看来能力值并不是像忠诚度那样要求最大,只是需要大于当前查询的就行了,换句话就是说,只要能力值不比当前的大,不管是在子树外面还是里面,都对答案没有贡献,对于每一个人,有可能替代他的就只有能力值比他大的而已,再在这些人里面选一个在其子树里面忠诚度最高的
思路出来了,这个思路也是很重要的
对于两个要求条件,可以把其中一个只是范围要求的要求,排序。先建一颗空树,将能力值排序后再按忠诚度加入线段树,这样在查询任意一个人时,线段树里有的值都是比当前人能力值大的
完整代码:
#include<stdio.h>#include<cstring>#include<algorithm>using namespace std;struct edge{ int v,last; int id,loy,aby;}ed[200010],a[100010];struct node{ int sum; node *ls,*rs; void update() { sum=max(ls->sum,rs->sum); }}pool[2000010],*root,*tail=pool,*null;int head[200010],inv[1000010],rec[100010],in[100010],ou[100010];int idx=0,num=0,n,m,T;bool cmp(const edge &a,const edge &b){ if(a.aby==b.aby) return a.id<b.id; return a.aby>b.aby;}void init(){ tail=pool; null=++tail; null->ls=null->rs=null; null->sum=0; idx=num=0; memset(head,0,sizeof(head)); memset(in,0,sizeof(in)); memset(ou,0,sizeof(ou)); memset(inv,0,sizeof(inv)); memset(rec,0,sizeof(rec));}void add(int u,int v){ num++; ed[num].v=v; ed[num].last=head[u]; head[u]=num;}node *newnode(){ node *nd=++tail; nd->ls=nd->rs=null; nd->sum=-1; return nd;}node *build(int lf,int rg){ node *nd=newnode(); if(lf==rg) return nd; int mid=(lf+rg)>>1; nd->ls=build(lf,mid); nd->rs=build(mid+1,rg); nd->update(); return nd;}void modify(node *nd,int lf,int rg,int pos,int delta){ if(lf==rg) { nd->sum=delta; return ; } int mid=(lf+rg)>>1; if(pos<=mid) modify(nd->ls,lf,mid,pos,delta); else modify(nd->rs,mid+1,rg,pos,delta); nd->update(); return ;}int query(node *nd,int lf,int rg,int L,int R){ if(L<=lf&&rg<=R) return nd->sum; int mid=(lf+rg)>>1,rt=-1; if(L<=mid) rt=max(rt,query(nd->ls,lf,mid,L,R)); if(R>mid) rt=max(rt,query(nd->rs,mid+1,rg,L,R)); return rt;}void dfs(int u,int fa){ in[u]=++idx; for(int i=head[u];i;i=ed[i].last) { int v=ed[i].v; if(v==fa) continue ; dfs(v,u); } ou[u]=idx;}int main(){ scanf("%d",&T); while(T--) { int v; init(); scanf("%d%d",&n,&m); for(int i=1;i<n;i++) { scanf("%d%d%d",&v,&a[i].loy,&a[i].aby),a[i].id=i,inv[a[i].loy]=i; add(i,v),add(v,i); } dfs(0,0); root=build(1,idx); sort(a+1,a+n,cmp); for(int i=1;i<n;i++) { int x=a[i].id; rec[x]=query(root,1,idx,in[x],ou[x]); if(rec[x]!=-1) rec[x]=inv[rec[x]]; modify(root,1,idx,in[x],a[i].loy); } while(m--) { scanf("%d",&v); printf("%d\n",rec[v]); } } return 0;}/*Whoso pulleth out this sword from this stone and anvil is duly born King of all England*/
嗯,就是这样
阅读全文
0 0
- HDU 4366 浅谈DFS序+线段树
- hdu 4366 Successor dfs序 + 线段树
- HDU 4366 (dfs序 线段树)
- hdu 4366(线段树+DFS序)
- 线段树+dfs HDU
- hdu 4366 线段树+dfs序列
- hdu 5039 Hilarity(dfs序 + 线段树)
- [HDU 5039 Hilarity] DFS序+线段树
- HDU 5039 Hilarity dfs序、线段树
- hdu 5039 线段树+dfs序
- HDU Hilarity (dfs序+线段树)
- HDU 5692 (线段树 dfs序)
- HDU 5692 Snacks dfs序 + 线段树
- hdu 5692 (dfs序+线段树)
- hdu 5692 Snacks(dfs序+线段树)
- HDU 5692 Snacks 【DFS序+线段树】
- HDU 5692(DFS序,线段树)
- HDU 3974(DFS序 + 线段树lazy)
- 使用appium+python对android进行自动化测试
- 2017/8/10开通博客,测试一下文章格式
- 解决谷歌chrome浏览器新版 58以上不支持浏览器编码的解决办法
- L
- opencv批量转换图片格式
- HDU 4366 浅谈DFS序+线段树
- 父元素设置absolute或relative,子元素设置fixed定位失效
- Shader学习笔记(四)
- js ==与===区别(两个等号与三个等号)
- 标签a的空链接问题
- Androidstudio新建项目到git@osc上
- Mob第三方短信注册
- 数据库初探
- Python3学习之字符编码问题解决办法详解