HDU 5877 Weak Pair 树状数组 + DFS

解决HDU 5877题目,通过DFS遍历和离线查询的方式,统计满足特定条件的祖先节点对数量。代码采用C++实现,涉及树形数据结构和区间查询算法。

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5877

题意:
求有序对个数(i,j)满足:
i是j的祖先节点,且ai * aj <= k

代码:

//#include <bits/stdc++.h>
#include <algorithm>
#include <cstdio>
#define sf scanf
#define pf printf
using namespace std;
const int maxn = 100000 + 5;
typedef __int64 INT;
int ins[maxn],n;
INT A[maxn], a[maxn],sorted[maxn],k,ans;
INT SUM(int p){
    INT ret = 0;
    for(;p;p -= p & -p) ret += A[p];
    return ret;
}
void ADD(int p,INT v){
    for(;p <= n;p += p & -p) A[p] += v;
}
int IDX(INT x){
    int idx = upper_bound(sorted + 1,sorted + 1 + n,x) - sorted;
    if(idx > n) idx = n;
    return idx;
}
struct Edge{
    int v,pre;
}Es[maxn];
int head[maxn],tot;
void INIT_EDGE(){
    memset(head,-1,sizeof head);
    tot = 0;
}
void ADD_EDGE(int u,int v){
    Es[tot].v = v;
    Es[tot].pre = head[u];
    head[u] = tot++;
}

void DFS(int cur){
    ans += SUM(a[cur] ? IDX(k / a[cur]) : n);
    ADD(IDX(a[cur]),1);
    for(int i = head[cur];~i;i = Es[i].pre) DFS(Es[i].v);
    ADD(IDX(a[cur]),-1);
}

void INIT(){
    INIT_EDGE();
    memset(A,0,sizeof A);
    memset(ins,0,sizeof ins);
    ans = 0;
}

int main(){
    int T,u,v,s;sf("%d",&T);
    while( T-- ){
        INIT();
        sf("%d%I64d",&n,&k);
        for(int i = 1;i <= n;++i) {sf("%I64d",&a[i]);sorted[i] = a[i];}
        for(int i = 0;i < n - 1;++i){sf("%d%d",&u,&v);ins[v]++;ADD_EDGE(u,v);}
        for(int i = 1;i <= n;++i) if(ins[i] == 0) {s = i;break;}
        sort(sorted + 1,sorted + 1 + n);
        DFS(s);
        pf("%I64d\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值