hdu5678 树上第k小

HDU - 5678 

题意:给一个n节点的树,给出m个询问,每次询问当前子树中权值的中位数,然后按求解答案,函数fmod(double x, double y) 表示x/y的余数,浮点数取模

思路:其实每次就是询问u节点为根的子树的树上第k小,k=size(u)/2,当然size要分奇偶,思路就是以dfs序建立前缀关系,然后套主席树即可(ps:updata的时候区间(l,mid)写成(1,mid),1和l不分调了一晚上,我怕是个傻子)

AC代码

#include "iostream"
#include "iomanip"
#include "string.h"
#include "stack"
#include "queue"
#include "string"
#include "vector"
#include "set"
#include "map"
#include "algorithm"
#include "stdio.h"
#include "math.h"
#pragma comment(linker, "/STACK:102400000,102400000")
#define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
#define mem(a,x) memset(a,x,sizeof(a))
#define step(x) fixed<< setprecision(x)<<
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define ll long long
#define endl ("\n")
#define ft first
#define sd second
#define lrt (rt<<1)
#define rrt (rt<<1|1)
using namespace std;
const ll mod=1e9+7;
const ll INF = 1e18+1LL;
const int inf = 1e9+1e8;
const double PI=acos(-1.0);
const int N=1e5+100;

int head[N*2], nex[N*2], to[N*2], siz[N], in[N], out[N], ran[N], tot, pos;
int rt[N], ls[N*20], rs[N*20], sum[N*20], cnt;
int n, m, a[N];
double ans[N];
struct Node {
    int v, id;
    bool friend operator< (Node a, Node b) {
        return a.v<b.v;
    }
}arr[N];
void addedge(int u, int v) {
    to[tot]=v, nex[tot]=head[u], head[u]=tot++;
}

void updata(int &cur, int l, int r, int p, int last) {
    cur = ++cnt;
    sum[cur] = sum[last]+1;
    ls[cur] = ls[last];
    rs[cur] = rs[last];
    if(l == r) return;
    int mid = l+r>>1;
    if(p <= mid) updata(ls[cur], l, mid, p, ls[last]);
    else updata(rs[cur], mid+1, r, p, rs[last]);
}

int query(int rt_l, int rt_r, int l, int r, int k) {
    if(l == r) return l;
    int tmp = sum[ls[rt_r]] - sum[ls[rt_l]];
    int mid = l+r>>1;
    if(k <= tmp) return query(ls[rt_l], ls[rt_r], l, mid, k);
    else return query(rs[rt_l], rs[rt_r], mid+1, r, k-tmp);
}

void dfs(int u, int fa) { //cout<<" UU "<<endl;
    in[u] = ++pos, siz[u] = 1; //arr[pos].v = a[u], arr[pos].id=pos;
    updata(rt[in[u]], 1, n, ran[u], rt[in[u]-1]);
    for(int i=head[u]; i!=-1; i=nex[i]) {
        int v = to[i];
        if(v == fa) continue;
        dfs(v, u);
        siz[u] += siz[v];
    }
    out[u] = pos;
}

int main(){
    int T; scanf("%d", &T);
    while(T--) {
        mem(head, -1), mem(sum, 0);
        cnt = pos = tot = 0;
        scanf("%d %d", &n, &m);
        for(int i=1; i<=n; ++i) {
            scanf("%d", &a[i]);
            arr[i].id = i, arr[i].v = a[i];
        }
        for(int i=1; i<n; ++i) {
            int u, v;
            scanf("%d %d", &u, &v);
            addedge(u, v), addedge(v, u);
        }
        sort(arr+1, arr+1+n);
        for(int i=1; i<=n; ++i) ran[arr[i].id] = i;
        dfs(1, 0);
        for(int i=1; i<=n; ++i) { //cout<<in[i]<<" "<<out[i]<<endl;
            if(siz[i] & 1)
                ans[i] = arr[query(rt[in[i]-1], rt[out[i]], 1, n, siz[i]/2+1)].v;
            else {
                double a, b;
                a = arr[query(rt[in[i]-1], rt[out[i]], 1, n, siz[i]/2)].v;
                b = arr[query(rt[in[i]-1], rt[out[i]], 1, n, siz[i]/2+1)].v;
                ans[i] = (a+b)/2;//cout<<a<<" "<<b<<endl;
            }
        }
        double ret = 0;
        for(int i=1; i<=m; ++i) {
            int u; scanf("%d", &u);
            ret=fmod(ans[u]+ret*10,1.0*mod);
        }
        printf("%.1f\n", ret);
    }
    return 0;
}

 

posted on 2018-04-21 21:19  lazzzy  阅读(228)  评论(0编辑  收藏  举报

导航