HDU 5678 (dfs序 + 主席树 查询子树中位数)

题目链接:芝麻开门

题意:给定一颗有根数,然后有m个询问,对于每个询问,求子树的中位数。最后按要求hash输出答案。

思路:对于子树问题,很显然是dfs序,然后就化成了区间第 k 大问题。可以说这个题是 裸的 dfs序 + 裸的主席树

有一点需要注意,要提前处理所有子树的答案,因为询问数是1e6,而结点数是1e5,在每个询问中query,会T。

贴上代码:

#include
#define debug(x) cout << "[" << #x <<": " << (x) <<"]"<< endl
#define pii pair
#define clr(a,b) memset((a),b,sizeof(a))
#define rep(i,a,b) for(int i = a;i < b;i ++)
#define pb push_back
#define MP make_pair
#define LL long long
#define ull unsigned LL
#define ls i << 1
#define rs i << 1 + 1
#define INT(t) int t; scanf("%d",&t)

using namespace std;

const int maxn = 1e5 + 10;
const int mod = 1000000007;
int head[maxn];
struct xx{
    int u,v,nex;
    xx(){}
    xx(int u,int v,int nex):
        u(u),v(v),nex(nex){}
}edg[maxn * 10];
int cnt = 0;
int IN[maxn],OUT[maxn],dfsx[maxn * 2];
int a[maxn];
int coun = 0;

void dfs(int p,int fa){
    dfsx[++ coun] = p;
    IN[p] = coun;
    for(int i = head[p]; ~i;i = edg[i].nex){
        int v = edg[i].v;
        if(fa == v) continue;
        dfs(v,p);
    }
    dfsx[++ coun] = p;
    OUT[p] = coun;
}

const int M = maxn * 40;
int T[M],lson[M],rson[M],C[M];
int X[maxn * 2],K[maxn * 2];
int tot = 0,en;

void init(){
    rep(i,0,maxn) head[i] = -1;
    cnt = coun = tot = 0;
}

int getId(int x){
    int pos = lower_bound(X + 1,X + 1 + en,x) - X;
    return pos;
}

int build(int l,int r){
    int rt = tot ++;
    C[rt] = 0;
    if(l != r){
        int mid = (l + r) >> 1;
        lson[rt] = build(l,mid);
        rson[rt] = build(mid + 1,r);
    }
    return rt;
}

int update(int rt,int pos,int val){
    int newrt = tot ++,tmp = newrt;
    C[newrt] = C[rt] + val;
    int l = 1,r = en;
    while(l < r){
        int mid = (l + r) >> 1;
        if(pos <= mid){
            lson[newrt] = tot ++;
            rson[newrt] = rson[rt];
            newrt = lson[newrt];
            rt = lson[rt];
            r = mid;
        }
        else {
            rson[newrt] = tot ++;
            lson[newrt] = lson[rt];
            newrt = rson[newrt];
            rt = rson[rt];
            l = mid + 1;
        }
        C[newrt] = C[rt] + val;
    }
    return tmp;
}

int query(int lrt,int rrt,int k){
    int l = 1,r = en;
    while(l < r){
        int mid = (l + r) >> 1;
        if(C[lson[rrt]] - C[lson[lrt]] >= k){
            r = mid;
            lrt = lson[lrt];
            rrt = lson[rrt];
        }
        else {
            l = mid + 1;
            k -= C[lson[rrt]] - C[lson[lrt]];
            lrt = rson[lrt];
            rrt = rson[rrt];
        }
    }
    return l;
}

double ANS[maxn];

int main() {
    int t; scanf("%d",&t);
    while(t --){
        init();
        int n,m; scanf("%d%d",&n,&m);
        for(int i = 1;i <= n;++ i){
            scanf("%d",&a[i]);
        }
        for(int i = 1;i < n;++ i){
            int u,v; scanf("%d%d",&u,&v);
            edg[cnt] = xx(u,v,head[u]);
            head[u] = cnt ++;
            edg[cnt] = xx(v,u,head[v]);
            head[v] = cnt ++;
        }
        dfs(1,-1);//debug(1);
//        for(int i = 1;i <= coun;++ i)
//            printf("%d ",dfsx[i]);printf("\n");
//        for(int i = 1;i <= n;++ i)
//            printf("%d %d\n",IN[i],OUT[i]);
        for(int i = 1;i <= coun;++ i){
            K[i] = a[dfsx[i]];
            X[i] = K[i];
        }
        sort(X + 1,X + 1 + coun);
        en = unique(X + 1,X + 1 + coun) - X - 1;

        T[0] = build(1,en);//debug(2);
        for(int i = 1;i <= coun;++ i){
            T[i] = update(T[i - 1],getId(K[i]),1);
        }//debug(3);
        for(int i = 1;i <= n;++ i){
            int num = OUT[i] - IN[i] + 1;
            if((num / 2) % 2 != 0){
                ANS[i] = X[query(T[IN[i] - 1],T[OUT[i]],num / 2)] * 1.0;
            }
            else {
                ANS[i] = (X[query(T[IN[i] - 1],T[OUT[i]],num / 2)] + X[query(T[IN[i] - 1],T[OUT[i]],num / 2 + 1)]) * 1.0 / 2;
            }
        }
        double ans = 0;
        for(int i = 1;i <= m;++ i){
            int root; scanf("%d",&root);
            ans = fmod(ANS[root] + ans * 10,1.0 * mod);
        }
        printf("%.1f\n",ans);
    }
    return 0;
}

 

你可能感兴趣的:(#,主席树)