• POJ 3067【树状数组】


    题意:
    给你两行数字,n个m个,然后给你k条线直接把两个数连起来,问有多少个交叉的
    思路:
    假定上一行是起点,下一行是终点。
    把路按照起点从大到下排序,
    然后可以直接对每条路查询,这条路目前的交叉数,等于sum[终点-1]条路相连,
    因为是起点是从大到小,终点是取一个前面点的路,所以肯定相交;
    具体处理就是利用树状数组存终点,每次取值,复杂度也低;
    然后这个K有问题…

    //#include <bits/stdc++.h>
    #include<iostream>
    #include<cstdio>
    #include<string.h>
    #include<algorithm>
    using namespace std;
    const int N=1e6+10;
    typedef long long LL;
    
    struct asd{
        int s,t;
    };
    asd q[N];
    
    bool cmp(asd a,asd b)
    {
        if(a.s>b.s)
            return 1;
        if(a.s==b.s)
            return a.t>b.t;
        return 0;
    }
    
    LL c[N];
    int n,m;
    
    int lowbit(int x)
    {
        return x&(-x);
    }
    void add(int i,LL v)
    {
        while(i<=n+7)
        {
            c[i]+=v;
            i+=lowbit(i);
        }
    }
    LL sum(int i)
    {
        LL ans=0;
        while(i>0)
        {
            ans+=c[i];
            i-=lowbit(i);
        }
        return ans;
    }
    int main()
    {
        int T;
        int cas=1;
        scanf("%d",&T);
        while(T--)
        {
            int num;
            LL ans;
            scanf("%d%d",&n,&m);
            scanf("%d",&num);
            for(int i=0;i<num;i++)
                scanf("%d%d",&q[i].s,&q[i].t);
            sort(q,q+num,cmp);
            memset(c,0,sizeof(c));
            ans=0;
            for(int i=0;i<num;i++)
            {
                int x=q[i].t;
                if(x>1)
                    ans+=sum(x-1);
                add(x,1);
            }
            printf("Test case %d: %lld
    ",cas++,ans);
        }
        return 0;
    }
    
  • 相关阅读:
    简易仿ios菊花加载loading图
    android 仿微信表情雨下落!
    android view 转Bitmap 生成截图
    设计模式——享元模式
    虚拟内存技术原理解析
    读史——回望勾吴
    android日志搜集原理及方案比较
    java四种引用及在LeakCanery中应用
    读史——秦历史概况
    git使用总结
  • 原文地址:https://www.cnblogs.com/keyboarder-zsq/p/5934788.html
Copyright © 2020-2023  润新知