• 【POJ3067】Japan-区间求和


    题目大意:一个平面,左边自上而下排列了N个点,标号为1,...,N,右边自上而下排列了M个点,标号为1,...,M,它们之间有K条线段相连,每条线段有两个值:x,y,表示该线段连接了左边的标号为x的点和右边的标号为y的点,问有多少个交点(除最初的点外)?

    做法:先对这些线段做双关键字排序,以x为主关键字升序排列,x相同时再以y为次关键字升序排列,再逐一插入这些线段,求出在它之前插入的线段中y大于当前线段的y的线段数目,把它累加到答案中,最终就可以得出答案。因为我们知道,如果两条线段有交点,那么必有一条线段的x小于另一条线段的x,而y大于另一条线段的y,又因为我们已经对x做了排序,所以只用求出y大于当前线段的y的线段数目即可。另外,由于答案可能会很大,所以需要使用__int64。

    由于树状数组编程复杂度较低,这里只贴树状数组的代码:

    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    int T,n,m,k;
    __int64 c[1010]={0},ans;
    struct road
    {
      int x,y;
    }e[1000010]={0};
    
    bool cmp(road a,road b)
    {
      if (a.x!=b.x) return a.x<b.x;
      else return a.y<b.y;
    }
    
    int lowbit(int i)
    {
      return i&(-i);
    }
    
    void add(int x,int a)
    {
      for(int i=x;i<=m;i+=lowbit(i))
        c[i]+=a;
    }
    
    int sum(int x)
    {
      int s=0;
      for(int i=x;i>0;i-=lowbit(i))
        s+=c[i];
      return s;
    }
    
    int main()
    {
      scanf("%d",&T);
      for(int t=1;t<=T;t++)
      {
        scanf("%d %d %d",&n,&m,&k);
    	for(int i=1;i<=k;i++)
    	  scanf("%d %d",&e[i].x,&e[i].y);
    	sort(e+1,e+k+1,cmp);
    	memset(c,0,sizeof(c));
    	ans=0;
    	for(int i=1;i<=k;i++)
    	{
    	  ans+=sum(m)-sum(e[i].y);
    	  add(e[i].y,1);
    	}
    	printf("Test case %d: %I64d
    ",t,ans);
      }
      
      return 0;
    }
    


  • 相关阅读:
    LOJ DFS序
    牛客练习赛31 D神器大师泰兹瑞与威穆
    Codeforces Round #487 (Div. 2) C
    Manthan, Codefest 18 (rated, Div. 1 + Div. 2) C D
    [Windows Server 2003] 还原SQL Server数据库
    [Windows Server 2008] 查看PHP详细错误信息
    [Windows Server 2008] 安装网站伪静态
    网站Gzip压缩
    [Windows Server 2008] SQL Server 2008 数据库还原方法
    [Windows Server 2008] 安装Apache+PHP+MySQL
  • 原文地址:https://www.cnblogs.com/Maxwei-wzj/p/9793994.html
Copyright © 2020-2023  润新知