Weak Pair---hud5877大连网选(线段树优化+dfs)

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

 题意:给你一颗树,有n个节点,每个节点都有一个权值v[i];现在求有多少对(u,v)满足u是v的祖先,并且au*av<=k, k是已知的;

思路:从根节点开始dfs遍历整棵树,当遍历到某点u时,已经在栈中的节点都是u的祖先的,所以我们只要找到在栈中的节点有多少个是<=k/a[u]的即可;

由于n的值最大可达到10e5,所以直接查找是会TLE的,我们可以用线段树优化即可;在dfs的时候插入当前节点的权值,在回溯的时候删除节点即可;

#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
#define met(a, b) memset(a, b, sizeof(a))
#define N 100005
typedef long long LL;
#define Lson r<<1
#define Rson r<<1|1

vector<int> G[N];
LL v[N], t[2*N], ans, k;
int du[N], m;

struct node
{
    int L, R;
    LL sum;
    int mid(){ return (L+R)/2; }
} a[N*8];

void Build(int r, int L, int R)
{
    a[r].L = L, a[r].R = R, a[r].sum = 0;
    if(L == R) return ;
    Build(Lson, L, a[r].mid());
    Build(Rson, a[r].mid()+1, R);
}

void Update(int r, int pos, LL num)
{
    if(a[r].L == a[r].R && a[r].L == pos)
    {
        a[r].sum += num;
        return ;
    }
    if(pos <= a[r].mid())
        Update(Lson, pos, num);
    else
        Update(Rson, pos, num);

    a[r].sum = a[Lson].sum + a[Rson].sum;
}

LL Query(int r, int L, int R)
{
    if(a[r].L == L && a[r].R == R)
        return a[r].sum;
    if(R <= a[r].mid())
        return Query(Lson, L, R);
    else if(L > a[r].mid())
        return Query(Rson, L, R);
    else
        return Query(Lson, L, a[r].mid()) + Query(Rson, a[r].mid()+1, R);
}

void dfs(int u)
{
    int pos1 = lower_bound(t+1, t+m+1, v[u]) - t;
    int pos2 = lower_bound(t+1, t+m+1, k/v[u]) - t;

    ans += Query(1, 1, pos2);

    Update(1, pos1, 1ll);

    for(int i=0, len=G[u].size(); i<len; i++)
        dfs(G[u][i]);

    Update(1, pos1, -1ll);
}

int main()
{
    int T, n;
    while(scanf("%d", &T) != EOF)
    {
        while(T--)
        {
            scanf("%d %I64d", &n, &k);
            for(int i=1; i<=n; i++)
            {
                scanf("%I64d", &v[i]);
                t[i] = v[i];
                t[i+n] = k/t[i];
                G[i].clear();
                du[i] = 0;
            }
            for(int i=1; i<n; i++)
            {
                int u, v;
                scanf("%d %d", &u, &v);
                G[u].push_back(v);
                du[v] ++;
            }
            sort(t+1, t+n*2+1);
            m = unique(t+1, t+n*2+1)-t-1;
            Build(1, 1, m);
            ans = 0;
            for(int i=1; i<=n; i++)
            {
                if(du[i] == 0)
                {
                    dfs(i);
                    ///break;
                }
            }
            printf("%I64d\n", ans);
        }
    }
    return 0;
}
/*
5
5 10
1 2 3 4 5
2 3
2 5
3 4
3 1

*/

时间: 2024-10-29 19:10:43

Weak Pair---hud5877大连网选(线段树优化+dfs)的相关文章

poj2104 求区间第k大 可持久化线段树

poj2104 求区间第k大  可持久化线段树 #include<iostream> #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef

Function---hdu5875(大连网选,区间连续求余)

题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5875 题意:有n个数,m个查询,每个查询有一个区间[L, R], 求ans, ans = a[L]%a[L+1]%a[L+2]%...%a[R]; 方法一:算是暴力吧,只能说数据太水: 用pos[i] = j 表示第 i 个元素后面的一个<= a[i]的下标是 j : 然后直接跳到当前位置即可,(我感觉如果数中有10e5个严格递减或者严格递增的序列是会TLE吧)但是这个还是过了,我想应该

HDU 1025-Constructing Roads In JGShining&#39;s Kingdom(最长不降子序列,线段树优化)

分析: 最长不降子序列,n很大o(n^2)肯定超,想到了小明序列那个题用线段树维护前面的最大值即可 该题也可用二分搜索来做. 注意问题输出时的坑,路复数后加s #include <map> #include <set> #include <list> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vecto

【bzoj3073】[Pa2011]Journeys 线段树优化建图+堆优化Dijkstra

题目描述 Seter建造了一个很大的星球,他准备建造N个国家和无数双向道路.N个国家很快建造好了,用1..N编号,但是他发现道路实在太多了,他要一条条建简直是不可能的!于是他以如下方式建造道路:(a,b),(c,d)表示,对于任意两个国家x,y,如果a<=x<=b,c<=y<=d,那么在xy之间建造一条道路.Seter保证不会有一个国家与自己之间有道路. Seter好不容易建好了所有道路,他现在在位于P号的首都.Seter想知道P号国家到任意一个国家最少需要经过几条道路.当然,Se

降临(线段树优化dp)

降临 选定点i会有代价\(c_i\),如果一个区间j内的点全被选择,就可以获得回报\(p_j\).点数和区间个数\(<1e5\). 还以为是线段树优化网络流(50万个点200万条边看上去很可做的样子毕竟lbn说过网络流20万万条边完全没问题),没想到是个线段树dp. (虽然这两个线段树完全扯不上关系) 用\(f[i][j]\)表示考虑到第i个点,向左最近的尚未选定的点为j时的最大值.那么,i+1可以选也可以不选.不选i时,\(f[i][j]\rightarrow f[i+1][i+1]\).选i

[Poi2010]Monotonicity 2 (线段树优化DP)

题目描述 给出N个正整数a[1..N],再给出K个关系符号(>.<或=)s[1..k].选出一个长度为L的子序列(不要求连续),要求这个子序列的第i项和第i+1项的的大小关系为s[(i-1)mod K+1].求出L的最大值. 输入 第一行两个正整数,分别表示N和K (N, K <= 500,000).第二行给出N个正整数,第i个正整数表示a[i] (a[i] <= 10^6).第三行给出K个空格隔开关系符号(>.<或=),第i个表示s[i]. 输出 一个正整数,表示L的

HDU4719-Oh My Holy FFF(DP线段树优化)

Oh My Holy FFF Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 606    Accepted Submission(s): 141 Problem Description N soldiers from the famous "*FFF* army" is standing in a line, from le

hdu 4719 Oh My Holy FFF(dp线段树优化)

Oh My Holy FFF Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65535/65535 K (Java/Others) Total Submission(s): 848    Accepted Submission(s): 219 Problem Description N soldiers from the famous "*FFF* army" is standing in a line, from le

【bzoj3939】[Usaco2015 Feb]Cow Hopscotch 动态开点线段树优化dp

题目描述 Just like humans enjoy playing the game of Hopscotch, Farmer John's cows have invented a variant of the game for themselves to play. Being played by clumsy animals weighing nearly a ton, Cow Hopscotch almost always ends in disaster, but this has