Network 【HDU - 3078】【LCA+暴力查詢】
阿新 • • 發佈:2018-12-09
題目連結
你要是真暴力這道題還是要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; }