POJ 3067【树状数组】

来源:互联网 发布:sql在哪里打开 编辑:程序博客网 时间:2024/06/01 10:19

题意:
给你两行数字,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\n",cas++,ans);    }    return 0;}
0 0