hdu5678 树上第k小
题意:给一个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; }