1. 程式人生 > >Network 【HDU - 3078】【LCA+暴力查詢】

Network 【HDU - 3078】【LCA+暴力查詢】

題目連結


  你要是真暴力這道題還是要T的,但是,做了剪枝就會過了,我們知道對於LCA每個節點有它自己的深度,在這裡,我就將每個節點的深度陣列當作了每個節點道最初根節點的距離了。

  然後,就是剪枝操作餓了:判斷是否是可行解的時候用的是dis[x]+dis[y]-2*dis[lca(x, y)]+1與Kth的大小關係即可,不然真會T,我試過。

  還有,別讀了道假題做半天,題目讓你求的是區間第K大,然後題目的測試樣例又給的很巧,所以,千萬要看清了!


#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define efs 1e-6
#define pi 3.141592653589793
#define e 2.718281828459045
using namespace std;
typedef unsigned long long ull;
typedef long long ll;
const int maxN = 80005;
int N, Q, a[maxN], cnt, head[maxN], depth[maxN], root[maxN][20], inque[maxN], num;
bool cmp(int e1, int e2) { return e1>e2; }
struct Eddge
{
    int nex, to;
    Eddge(int a=-1, int b=0):nex(a), to(b) {}
}edge[maxN<<1];
void addEddge(int u, int v)
{
    edge[cnt] = Eddge(head[u], v);
    head[u] = cnt++;
}
void dfs(int u, int fa, int deep)
{
    root[u][0] = fa;
    depth[u] = deep;
    for(int i=head[u]; i!=-1; i=edge[i].nex)
    {
        int v = edge[i].to;
        if(v == fa) continue;
        dfs(v, u, deep+1);
    }
}
void pre_did()
{
    dfs(1, -1, 0);
    for(int j=0; ((1<<(j+1))<N); j++)
    {
        for(int i=1; i<=N; i++)
        {
            if(root[i][j]<0) root[i][j+1] = -1;
            else root[i][j+1] = root[root[i][j]][j];
        }
    }
}
int LCA(int x, int y)
{
    if(depth[x] > depth[y]) swap(x, y);
    int deth = depth[y] - depth[x];
    for(int i=(int)log2(1.*deth); i>=0; i--)
    {
        if((1<<i) & deth) y = root[y][i];
    }
    if(x == y) return x;
    for(int i=(int)log2(1.*N); i>=0; i--)
    {
        if(root[x][i] != root[y][i])
        {
            x = root[x][i];
            y = root[y][i];
        }
    }
    return root[x][0];
}
void query(int x, int y, int Kth)
{
    int fa = LCA(x, y);
    if(depth[x] + depth[y] - 2*depth[fa] + 1 < Kth) { printf("invalid request!\n"); return; }
    num = 0;
    inque[++num] = a[fa];
    while(x != fa)
    {
        inque[++num] = a[x];
        x = root[x][0];
    }
    while(y != fa)
    {
        inque[++num] = a[y];
        y = root[y][0];
    }
    sort(inque+1, inque+1+num, cmp);
    printf("%d\n", inque[Kth]);
}
void init()
{
    cnt = 0;
    memset(head, -1, sizeof(head));
    memset(root, -1, sizeof(root));
}
int main()
{
    scanf("%d%d", &N, &Q);
    for(int i=1; i<=N; i++) scanf("%d", &a[i]);
    init();
    for(int i=1; i<N; i++)
    {
        int e1, e2;
        scanf("%d%d", &e1, &e2);
        addEddge(e1, e2);
        addEddge(e2, e1);
    }
    pre_did();
    int op, L, R;
    while(Q--)
    {
        scanf("%d%d%d", &op, &L, &R);
        if(op == 0) a[L] = R;
        else query(L, R, op);
    }
    return 0;
}