hdu3078 伪LCA……

题意:有 n 点的一颗树,每个节点有格子的权值,现在有两种操作,修改一个点的权值,或者求两点之间的路径上的第 k 大的权值。

其实看到这个题,就在 YY 各种做法,询问后得到貌似可能是关于主席树、树链剖分等高端数据结构做的,但事实上,大概是出题人也并不想出难题,只是为了练练手所以……直接把每个问题路径上的点权保存在数组中 sort 一下就行了。然后树上路径就果断是LCA了,不过这里LCA也就不用倍增了,直接一步一步向上爬然后顺便加数组就行了。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5
 6 const int maxn=8e4+5;
 7 const int maxm=maxn*2;
 8
 9 int fa[maxn],dep[maxn];
10 int head[maxn],point[maxm],nxt[maxm],size;
11 int n,num[maxn],que[maxn],cnt;
12
13 void init(){
14     size=0;
15     memset(head,-1,sizeof(head));
16 }
17
18 void add(int a,int b){
19     point[size]=b;
20     nxt[size]=head[a];
21     head[a]=size++;
22     point[size]=a;
23     nxt[size]=head[b];
24     head[b]=size++;
25 }
26
27 void Dfs(int s,int pre){
28     fa[s]=pre;
29     dep[s]=dep[pre]+1;
30     for(int i=head[s];~i;i=nxt[i]){
31         int j=point[i];
32         if(j==pre)continue;
33         Dfs(j,s);
34     }
35 }
36
37 void Pre(){
38     dep[1]=0;
39     Dfs(1,-1);
40 }
41
42 void Lca(int u,int v){
43     cnt=0;
44     if(dep[u]>dep[v])swap(u,v);
45     while(dep[u]<dep[v]){
46         que[++cnt]=num[v];
47         v=fa[v];
48     }
49     while(u!=v){
50         que[++cnt]=num[u];
51         u=fa[u];
52         que[++cnt]=num[v];
53         v=fa[v];
54     }
55     que[++cnt]=num[u];
56 }
57
58 int main(){
59     int m;
60     scanf("%d%d",&n,&m);
61     init();
62     for(int i=1;i<=n;++i)scanf("%d",&num[i]);
63     for(int i=1;i<n;++i){
64         int a,b;
65         scanf("%d%d",&a,&b);
66         add(a,b);
67     }
68     Pre();
69     while(m--){
70         int f,a,b;
71         scanf("%d%d%d",&f,&a,&b);
72         if(f){
73             Lca(a,b);
74             if(cnt<f)printf("invalid request!\n");
75             else{
76                 sort(que+1,que+cnt+1);
77                 printf("%d\n",que[cnt-f+1]);
78             }
79         }
80         else num[a]=b;
81     }
82 }

时间: 2024-10-29 19:06:14

hdu3078 伪LCA……的相关文章

[hdu3078]Network(LCA+排序)

题意:维护树上两点之间的最短路径,其一,将点a的值变为b,其二,求路径上第k大的值. 解题关键:LCA+sort 复杂度:$O(qn\log n + n\log n)$ 数据弱不怪我 1 //#pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<

hdu3078 建层次树+在线LCA算法+排序

题意:n个点,n-1条边构成无向树,每个节点有权,Q次询问,每次或问从a->b的最短路中,权第k大的值,/或者更新节点a的权, 思路:在线LCA,先dfs生成树0,标记出层数和fa[](每个节点的父亲节点).在对每次询问,走一遍一次公共祖先路上 的权,保持,快排.n*logn*q #include<iostream> //187MS #include<algorithm> #include<cstdio> #include<vector> using

hdu3078(lca / RMQ在线)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3078 题意: 给出一棵 n 个点的带点权值的树, 接下来有 q 组形如 k, x, y 的输入, 若 k == 0 则将 x 点的权值替换成 y, 否则输出 x 到 y 之间顶点地 k 大的权值. 思路: 用一个数组 val 记录一下每个顶点的权值, 对于k == 0, 直接令 val[x] = y 即可 . 对于询问, 可以先求出 lca, 再记录一下路径上的顶点的权值, sort 一下, 输出

HDU3078 Network (倍增LCA算法求树链)

题意: 一棵无向树,输入点数和操作数,下面一行n个值代表每个点的权.下面n-1行是树边 操作分为 0 x w ,表示把点x的权改为w: k a b , 求出,从a到b的路径中,第k大的点权 题解: 对于每组询问,先求出两点的LCA,再从两点分别向LCA遍历,保存路径上所有的点权,排序输出第K大即可~ #include<cstdio> #include<algorithm> #include<cstring> #include<vector> using na

学习 LCA&amp;&amp;RMQ

参考:点击打开链接 点击打开链接      点击打开链接(一些总结) 点击打开链接(不错的模板) 题目:点击打开链接 花了4天时间做完了这个专题,LCA的问题用处还是很大,同时能体会RMQ的ST算法中dp的味道.基本方法就是ST,LCA转RMQ,LCA的Tarjan,LCA倍增(这个可存储边权) 这个专题后面四道题都非常好,推荐大家做做. 细节: 1. ST方法2^i 包含自己,因此其真实只包含到i+2^k-1的范围. 2. Tarjan一般都很快,但不适合修改类型的问题,关于权值长度之类的,S

LCA&amp;&amp;RMQ问题

参考:点击打开链接 点击打开链接      点击打开链接(一些总结) 点击打开链接(不错的模板) 题目:点击打开链接 花了4天时间做完了这个专题,LCA的问题用处还是很大,同时能体会RMQ的ST算法中dp的味道.基本方法就是ST,LCA转RMQ,LCA的Tarjan,LCA倍增(这个可存储边权) 这个专题后面四道题都非常好,推荐大家做做. 细节: 1. ST方法2^i 包含自己,因此其真实只包含到i+2^k-1的范围. 2. Tarjan一般都很快,但不适合修改类型的问题,关于权值长度之类的,S

暂且叫它-&quot;蒙伪树&quot;-吧-

今天我看到ooo聚聚画线段树,但是ta画的不是很好,于是本人饶有兴趣的研究了那棵无聊的树. 但是它并不满足树的性质,于是命名为伪树. 为了防止太弱和别的巨型数据结构撞名导致尴尬,于是又挂了自己$id$的一部分,叫"蒙伪树"($\text{Miemeng's Erroneous Tree}$)可以简称$\text{MET}$. 其实是样辉三角? 我伪了. 先来张图: 有啥用: 显然没啥用,可以用上面多的要命的节点维护区间最值,或是一些其他的信息. 时间复杂度: 建树:$O(N^2)$ 查

HDU 6203 ping ping ping [LCA,贪心,DFS序,BIT(树状数组)]

题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=6203] 题意 :给出一棵树,如果(a,b)路径上有坏点,那么(a,b)之间不联通,给出一些不联通的点对,然后判断最少有多少个坏点. 题解 :求每个点对的LCA,然后根据LCA的深度排序.从LCA最深的点对开始,如果a或者b点已经有点被标记了,那么continue,否者标记(a,b)LCA的子树每个顶点加1. #include<Bits/stdc++.h> using namespace std;

SZOJ 167 Lca裸题

一道.......一道我改了一周的裸题 无根树建双向边 无根树建双向边 无根树建双向边 重要的事情说三遍(微笑) 还有要开longlong 还有双向边不是双倍边(微笑) 我真是,能把自己气吐血10次就不把自己气吐血9次 [问题描述] 已知一棵nn个点的树,点从1开始标号,树上每条边都有一个正整数边权. 有qq个询问,每个询问由type,u,vtype,u,v三个正整数构成. 当type=1type=1时,询问uu到vv路径上所有边权的二进制异或和. 当type=2type=2时,询问uu到vv路