zoukankan      html  css  js  c++  java
  • 2016 ACM/ICPC Asia Regional Dalian Online 1010 Weak Pair dfs序+分块

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)
    Total Submission(s): 3192    Accepted Submission(s): 371


    Problem Description
    You are given a rooted tree of N nodes, labeled from 1 to N. To the ith node a non-negative value ai is assigned.An ordered pair of nodes (u,v) is said to be weak if
      (1) u is an ancestor of v (Note: In this problem a node u is not considered an ancestor of itself);
      (2) au×avk.

    Can you find the number of weak pairs in the tree?
     
    Input
    There are multiple cases in the data set.
      The first line of input contains an integer T denoting number of test cases.
      For each case, the first line contains two space-separated integers, N and k, respectively.
      The second line contains N space-separated integers, denoting a1 to aN.
      Each of the subsequent lines contains two space-separated integers defining an edge connecting nodes u and v , where node u is the parent of node v.

      Constrains: 
      
      1N105 
      
      0ai109 
      
      0k1018
     
    Output
    For each test case, print a single integer on a single line denoting the number of weak pairs in the tree.
     
    Sample Input
    1
    2 3
    1 2
    1 2
     
    Sample Output
    1
     
    题意:给你一颗根树,求有多少点对(u,v)  u!=v满足u是v的祖先且点权au*av<=k
    思路:问题转化一下,就是求对于每一个点u,以该点为根的子树下,有多少个点v的权值是小于等于(k/au + 1); 由于是子树的问题,那么可以想到的是先求出一个dfs序,将问题转化为区间查询的问题,那么问题就是,对于每个点u,在区间[st[u]+1,ed[u]]有多少个值是小于等于(k/au + 1); 求一个区间有多少个数小于莫个数G的数可以用分块实现,就是完整的块二分,两边的块暴力, 复杂度nsqrt(n)  
    坑点:一直以为1就是root。。。
     
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    #include <queue>
    #include <algorithm>
    #include <stack>
    #include <queue>
    #include <map>
    #include <set>
    #include <vector>
    #include <cstdlib>
    using namespace std;
    typedef long long ll;
    const int maxn = 3e5 + 100;
    struct Edge {
        int to, nex;
    }e[maxn];
    int n;
    ll k;
    ll a[maxn];
    int root;
    int head[maxn], tot;
    void init() {
        memset(head, -1, sizeof head);
        tot = 0;
    }
    void add(int u, int v) {
        e[tot].to = v;
        e[tot].nex = head[u];
        head[u] = tot++;
    }
    ll id[maxn];
    int flag[maxn];
    void input() {
        scanf("%d%I64d", &n, &k);
        memset(flag, 0, sizeof flag);
        for(int i = 0; i < n; ++i) scanf("%I64d", &a[i]);
        int u, v;
        for(int i = 1; i < n; ++i) {
            scanf("%d%d", &u, &v);
            u--; v--;
            flag[v] = 1;
            add(u, v);
        }
        for(int i = 0; i < n; ++i) if(flag[i] == 0) { root = i; break; }
    }
    int st[maxn], ed[maxn], tim;
    void dfs(int u) {
        st[u] = ++tim;
        id[tim] = a[u];
        for(int i = head[u]; ~i; i = e[i].nex) {
            dfs(e[i].to);
        }
        ed[u] = tim;
    }
    
    
    const int SIZE = 937;
    ll block[maxn / SIZE + 1][SIZE + 1];
    void init2() {
        int b = 0, j = 0;
        for(int i = 0; i < n; ++i) {
            block[b][j] = id[i];
            if(++j == SIZE) { b++; j = 0; }
        }
        for(int i = 0; i < b; ++i) sort(block[i], block[i] + SIZE);
        if(j) sort(block[b], block[b] + j);
    }
    
    int query(int L, int R, ll v) {
        int lb = L / SIZE, rb = R / SIZE;
        int k = 0;
        if(lb == rb) {
            for(int i = L; i <= R; ++i) if(id[i] < v) k++;
        } else {
            for(int i = L; i < (lb + 1) * SIZE; ++i) if(id[i] < v) k++;
            for(int i = rb * SIZE; i <= R; ++i) if(id[i] < v) k++;
            for(int b = lb + 1; b < rb; ++b) {
                k += lower_bound(block[b], block[b] + SIZE, v) - block[b];
            }
        }
        return k;
    }
    void solve() {
        tim = -1;
        dfs(root);
        init2();
       ll ans = 0;
       for(int i = 0; i < n; ++i) {
            if(st[i] == ed[i]) continue;
            if(a[i] == 0) { ans += (ed[i] - st[i]); continue; }
            ll v = k / a[i] + 1;
            ans += query(st[i]+1, ed[i], v);
    
       }
       printf("%I64d
    ", ans);
    }
    int main() {
    #ifdef LOCAL
        freopen("in", "r", stdin);
    #endif
    int cas;
        while(~scanf("%d", &cas)) {
        //int cas;
            while(cas --) {
                init();
                input();
                solve();
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    330. Patching Array--Avota
    334. Increasing Triplet Subsequence My Submissions Question--Avota
    C++前置++与后置++的区别与重载
    OpenGL光源位置
    深度探索va_start、va_arg、va_end
    C++类型转换
    2019-2020-2 20175216 《网络对抗技术》Exp9 Web安全基础
    2019-2020-2 20175216 《网络对抗技术》Exp8 Web基础
    2019-2020-2 20175216 《网络对抗技术》Exp7 网络欺诈防范
    2019-2020-2 20175216 《网络对抗技术》Exp6 MSF基础应用
  • 原文地址:https://www.cnblogs.com/orchidzjl/p/5861153.html
Copyright © 2011-2022 走看看