hdu3087 LCA + 暴力

Network

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 903    Accepted Submission(s): 379

Problem Description

The ALPC company is now working on his own network system, which is connecting all N ALPC department. To economize on spending, the backbone network has only one router for each department, and N-1 optical fiber in total to connect all routers.
The usual way to measure connecting speed is lag, or network latency, referring the time taken for a sent packet of data to be received at the other end.
Now the network is on trial, and new photonic crystal fibers designed by ALPC42 is trying out, the lag on fibers can be ignored. That means, lag happened when message transport through the router. ALPC42 is trying to change routers to make the network faster, now he want to know that, which router, in any exactly time, between any pair of nodes, the K-th high latency is. He needs your help.

Input

There are only one test case in input file.
Your program is able to get the information of N routers and N-1 fiber connections from input, and Q questions for two condition: 1. For some reason, the latency of one router changed. 2. Querying the K-th longest lag router between two routers.
For each data case, two integers N and Q for first line. 0<=N<=80000, 0<=Q<=30000.
Then n integers in second line refer to the latency of each router in the very beginning.
Then N-1 lines followed, contains two integers x and y for each, telling there is a fiber connect router x and router y.
Then q lines followed to describe questions, three numbers k, a, b for each line. If k=0, Telling the latency of router a, Ta changed to b; if k>0, asking the latency of the k-th longest lag router between a and b (include router a and b). 0<=b<100000000.
A blank line follows after each case.

Output

For each question k>0, print a line to answer the latency time. Once there are less than k routers in the way, print "invalid request!" instead.

Sample Input


5 5 5 1 2 3 4 3 1 2 1 4 3 5 3 2 4 5 0 1 2 2 2 3 2 1 4 3 3 5

Sample Output

3 2 2 invalid request!

题意:

n个点的树,2中操作,如果k为0,修改a点的值为b,如果K > 0,求[x,y]的第k大值。

思路:

其实一开始我没有很好的想法。因为如果这是一条链,并且每次操作都是查询[1,n]的第k大,那么这样的写法会超时!

求x,y的lca,然后分别从x,y找到祖先,记录排序,找到第k大值。

/*
 * Author:  sweat123
 * Created Time:  2016/7/13 14:46:25
 * File Name: main.cpp
 */
#include<set>
#include<map>
#include<queue>
#include<stack>
#include<cmath>
#include<string>
#include<vector>
#include<cstdio>
#include<time.h>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 1<<30
#define MOD 1000000007
#define ll long long
#define lson l,m,rt<<1
#define key_value ch[ch[root][1]][0]
#define rson m+1,r,rt<<1|1
#define pi acos(-1.0)
using namespace std;
const int MAXN = 80010;
struct node{
    int to;
    int next;
}edge[MAXN*2];
int dp[MAXN*2][20],ind,pre[MAXN],a[MAXN],first[MAXN],rev[MAXN*2],tot,dfn[MAXN*2],vis[MAXN],fa[MAXN],n,m;
void add(int x,int y){
    edge[ind].to = y;
    edge[ind].next = pre[x];
    pre[x] = ind ++;
}
bool cmp(int x,int y){
    return x > y;
}
void dfs(int rt,int deq,int pa){
    vis[rt] = 1;
    rev[++tot] = rt;
    fa[rt] = pa;
    dfn[tot] = deq;
    first[rt] = tot;
    for(int i = pre[rt]; i != -1; i = edge[i].next){
        int t = edge[i].to;
        if(!vis[t]){
            dfs(t,deq+1,rt);
            rev[++tot] = rt;
            dfn[tot] = deq;
        }
    }
}
int b[MAXN],cnt;
void rmq(){
    for(int i = 1; i <= tot; i++){
        dp[i][0] = i;
    }
    for(int i = 1; i < 20; i++){
        for(int j = 1; j + (1 << i) - 1 <= tot; j++){
            int x = dp[j][i-1];
            int y = dp[j+(1<<(i-1))][i-1];
            if(dfn[x] > dfn[y]){
                dp[j][i] = y;
            } else{
                dp[j][i] = x;
            }
        }
    }
}
int lca(int x,int y){
    x = first[x];
    y = first[y];
    if(x > y)swap(x,y);
    int k = (int)(log(y - x + 1) * 1.0 / log(2.0));
    int l = dp[x][k];
    int r = dp[y - (1<<k) + 1][k];
    if(dfn[l] > dfn[r]){
        return r;
    } else {
        return l;
    }
}
int main(){
    while(~scanf("%d%d",&n,&m)){
        for(int i = 1; i <= n; i++)scanf("%d",&a[i]);
        ind = 0;
        memset(pre,-1,sizeof(pre));
        for(int i = 1; i < n; i++){
            int x,y;
            scanf("%d%d",&x,&y);
            add(x,y),add(y,x);
        }
        tot = 0;
        memset(vis,0,sizeof(vis));
        dfs(1,1,-1);
        rmq();
        while(m --){
            int k,x,y;
            scanf("%d%d%d",&k,&x,&y);
            if(k == 0){
                a[x] = y;
            } else{
                if(y > n){
                    printf("invalid request!\n");
                    continue;
                }
                cnt = 0;
                int tp = rev[lca(x,y)];
                b[cnt++] = a[tp];
                while(x != tp){
                    b[cnt++] = a[x];
                    x = fa[x];
                }
                while(y != tp){
                    b[cnt++] = a[y];
                    y = fa[y];
                }
                sort(b,b+cnt,cmp);
                if(k > cnt) printf("invalid request!\n");
                else printf("%d\n",b[k-1]);
            }
        }
    }
    return 0;
}
时间: 2024-11-06 03:47:25

hdu3087 LCA + 暴力的相关文章

【bzoj3251】树上三角形 朴素LCA+暴力

题目描述 给定一大小为n的有点权树,每次询问一对点(u,v),问是否能在u到v的简单路径上取三个点权,以这三个权值为边长构成一个三角形.同时还支持单点修改. 输入 第一行两个整数n.q表示树的点数和操作数 第二行n个整数表示n个点的点权 以下n-1行,每行2个整数a.b,表示a是b的父亲(以1为根的情况下) 以下q行,每行3个整数t.a.b 若t=0,则询问(a,b) 若t=1,则将点a的点权修改为b 输出 对每个询问输出一行表示答案,“Y”表示有解,“N”表示无解. 样例输入 5 5 1 2

hdu 6115(LCA 暴力)

Factory Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 132768/132768 K (Java/Others)Total Submission(s): 367    Accepted Submission(s): 124 Problem Description 我们将A省简化为由N个城市组成,某些城市之间存在双向道路,而且A省的交通有一个特点就是任意两个城市之间都能通过道路相互到达,且在不重复经过城市的情况下任意两个

POJ - 2763 Housewife Wind(LCA+暴力)

题目大意:给出N个点,M条边和一个人的起始位置,然后给出一系列操作 操作A: 0 u 询问这个人走到u这个位置需要几分钟 操作B: 1 i w,将第i条边的权值改成w 解题思路:第一个操作比较简单,第二个操作的话也不难. 在dfs纪录结点出现的顺序的时候,顺便记录一下每个点的pre,为第二个操作做准备. 执行第二个操作时,先把本来的边改变一下,再用一次dfs将该边以下的边全部该变一下就好了,这时pre数组就有用了,因为它标记了哪几个点是和该边有关的 #include <cstdio> #inc

洛谷 P3384 【模板】树链剖分

题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和 操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z 操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和 输入输出格式 输入格式: 第一行包含4个正整数N.M.R.P,分别表示树的结点个数.操作个数

luogu3384 【模板】树链剖分

P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和 操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z 操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和 输入输出格式 输入格式: 第一行包含4个正整数N.M.R.P,

洛谷——P3384 【模板】树链剖分

https://www.luogu.org/problem/show?pid=3384#sub 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和 操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z 操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之

P3384 【模板】树链剖分

P3384 [模板]树链剖分 题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和 操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z 操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和 输入输出格式 输入格式: 第一行包含4个正整数N.M.R.P,

洛谷P3384 【模板】树链剖分

题目描述 如题,已知一棵包含N个结点的树(连通且无环),每个节点上包含一个数值,需要支持以下操作: 操作1: 格式: 1 x y z 表示将树从x到y结点最短路径上所有节点的值都加上z 操作2: 格式: 2 x y 表示求树从x到y结点最短路径上所有节点的值之和 操作3: 格式: 3 x z 表示将以x为根节点的子树内所有节点值都加上z 操作4: 格式: 4 x 表示求以x为根节点的子树内所有节点值之和 输入输出格式 输入格式: 第一行包含4个正整数N.M.R.P,分别表示树的结点个数.操作个数

【NOIP2013提高组】货车运输

https://www.luogu.org/problem/show?pid=1967 思考一下,将图的所有边按边权从大到小依次加入图,则当u与v第一次连通时,刚加入的边就是使u与v两点的路径中的最小边最大的边. 将图的所有边按边权从大到小依次加入图?这不就是Kruscal算法最大生成树吗! 所以我们只需要对原图求最大生成树,对于每个询问求两点的路径上的最小边就可以了.虽然可以用树剖+ST表优化,但是暴力求LCA+暴力爬链也能过了. 暴力LCA+暴力爬链: #include <algorithm