• HDU 5877 dfs+ 线段树(或+树状树组)


    1、HDU 5877  Weak Pair   

    2、总结:有多种做法,这里写了dfs+线段树(或+树状树组),还可用主席树或平衡树,但还不会这两个

    3、思路:利用dfs遍历子节点,同时对于每个子节点au,查询它有多少个祖先av满足av<=k/au。

    (1)dfs+线段树

    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    #include<cstdio>
    #define F(i,a,b) for (int i=a;i<b;i++)
    #define FF(i,a,b) for (int i=a;i<=b;i++)
    #define mes(a,b) memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define LL long long
    using namespace std;
    const int N=101000,MAX=1000100;
    
    LL k,a[N],b[N*2];
    int n,m,tree[N*8],head[N],in[N];    //注:N*8,不是N*4,因为m可能会是n的2倍
    
    struct Edge
    {
        int to,nexte;
    }edge[N*2];
    
    int tot;
    void AddEdge(int u,int v)
    {
        edge[tot].to=v;
        edge[tot].nexte=head[u];
        head[u]=tot++;
    }
    
    void update(int pos,int l,int r,int ro,int val)
    {
        if(l==r){
            tree[ro]+=val;
            return ;
        }
        int mid=(l+r)>>1;
        if(pos<=mid)update(pos,l,mid,ro<<1,val);
        else update(pos,mid+1,r,ro<<1|1,val);
        tree[ro]=tree[ro<<1]+tree[ro<<1|1];
    }
    
    int query(int R,int l,int r,int ro,int L)
    {
        if(R>=r&&l>=L){     //注:返回条件
            return tree[ro];
        }
        int mid=(l+r)>>1;
        if(R<=mid)return query(R,l,mid,ro<<1,L);
        else if(L>mid)return query(R,mid+1,r,ro<<1|1,L);
        else return query(mid,l,mid,ro<<1,L)+query(R,mid+1,r,ro<<1|1,mid+1);   //注:要拆分区间
    }
    
    LL ans;
    void dfs(int r)
    {
        int pos=lower_bound(b+1,b+1+m,a[r])-b;  //注:lower_bound(), -b不是-(b+1)
        int posk=lower_bound(b+1,b+1+m,k/a[r])-b;
        ans+=1ll*query(posk,1,m,1,1);
        update(pos,1,m,1,1);
        for(int i=head[r];i!=-1;i=edge[i].nexte){
            dfs(edge[i].to);        //利用dfs序遍历子孙
        }
        update(pos,1,m,1,-1);
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%I64d",&n,&k);
            FF(i,1,n){
                scanf("%I64d",&a[i]);
                b[i]=a[i];
            }
            m=n;
            FF(i,1,n) b[++m]=k/a[i];
            sort(b+1,b+1+m);    //排序,离散基础
            m=unique(b+1,b+1+m)-(b+1);  //注:unique(), -(b+1)不是-b
    
            mes(head,-1);
            int u,v;
            mes(in,0);
            ans=tot=0;
            FF(i,1,n-1){
                scanf("%d%d",&u,&v);
                AddEdge(u,v);
                in[v]++;
            }
            mes(tree,0);
            FF(i,1,n){
                if(!in[i]){
                    dfs(i);break;
                }
            }
            printf("%I64d
    ",ans);
        }
    
        return 0;
    }
    View Code

    (2)dfs+树状树组

    这个刚学,还不太懂

    #include<iostream>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    #include<cstdio>
    #define F(i,a,b) for (int i=a;i<b;i++)
    #define FF(i,a,b) for (int i=a;i<=b;i++)
    #define mes(a,b) memset(a,b,sizeof(a))
    #define INF 0x3f3f3f3f
    #define LL long long
    using namespace std;
    const int N=100100,MAX=1000100;
    
    LL k,a[N],b[N*2],c[N*2];
    int n,m,head[N],in[N];
    
    struct Edge
    {
        int to,nexte;
    }edge[N*2];
    
    int tot;
    void AddEdge(int u,int v)
    {
        edge[tot].to=v;
        edge[tot].nexte=head[u];
        head[u]=tot++;
    }
    
    int Lowbit(int x)
    {
        return x&(-x);
    }
    
    void update(int pos,int val)
    {
        for(int i=pos;i<=m;i+=Lowbit(i)){     //
            c[i]+=val;
        }
    }
    
    LL Sum(int posk)
    {
        LL ans=0;
        for(int i=posk;i>0;i-=Lowbit(i)){      //
            ans+=c[i];
        }
        return ans;
    }
    
    LL ans;
    void dfs(int r)
    {
        int pos=lower_bound(b+1,b+1+m,a[r])-b;
        int posk=upper_bound(b+1,b+1+m,k/a[r])-(b+1);   //注:upper_bound(),-(b+1)不是-b
        ans+=Sum(posk);
        update(pos,1);
        for(int i=head[r];i!=-1;i=edge[i].nexte){
            dfs(edge[i].to);
        }
        update(pos,-1);
    }
    
    int main()
    {
        int t;
        scanf("%d",&t);
        while(t--)
        {
            scanf("%d%I64d",&n,&k);
            FF(i,1,n){
                scanf("%I64d",&a[i]);
                b[i]=a[i];
            }
            m=n;
            FF(i,1,n) b[++m]=k/a[i];
            sort(b+1,b+1+m);
            m=unique(b+1,b+1+m)-(b+1);
    
            mes(head,-1);
            mes(c,0);
            int u,v;
            mes(in,0);
            ans=tot=0;
            FF(i,1,n-1){
                scanf("%d%d",&u,&v);
                AddEdge(u,v);
                in[v]++;
            }
            FF(i,1,n){
                if(!in[i]){
                    dfs(i);break;
                }
            }
            printf("%I64d
    ",ans);
        }
    
        return 0;
    }
    View Code
  • 相关阅读:
    9 *9 乘法表
    总结day04 ---- 列表的切片,增删改查,以及,相关方法, 元祖的使用方法
    三级菜单 -----待学习,待强化
    day04 --class --homework
    购物车项目 复杂版本.待简化
    python 学习资料 常用
    总结day3 ---- 进制转换,字符串切片,字符串常用方法.,for 循环,
    day03 --class --homework
    总结day2 ---- while循环的简单使用, 格式化输出.运算符.以及编码的应用
    Uva 10054 欧拉回路 打印路径
  • 原文地址:https://www.cnblogs.com/sbfhy/p/5929099.html
Copyright © 2020-2023  润新知