题目描述
Japan plans to welcome the ACM ICPC World Finals and a lot of roads must be built for the venue. Japan is tall island with N cities on the East coast and M cities on the West coast (M <= 1000, N <= 1000). K superhighways will be build. Cities on each coast are numbered 1, 2, … from North to South. Each superhighway is straight line and connects city on the East coast with city of the West coast. The funding for the construction is guaranteed by ACM. A major portion of the sum is determined by the number of crossings between superhighways. At most two superhighways cross at one location. Write a program that calculates the number of the crossings between superhighways.
题目大意
日本计划欢迎ACM ICPC世界总决赛和很多道路必须建的场馆。日本高岛与N在东海岸的城市和我的城市在西海岸(M ≤ 1000,n≤1000)。K高速公路将建。在每一个沿海城市,编号1,2,…从北到南。每个高速公路直线连接城市在东海岸和西海岸的城市。对于建设资金保证是ACM。总结的主要部分是由口岸之间的高速公路的数量确定。最多两高速公路交叉在一个位置。写一个程序,计算之间的高速公路的交叉数。
数据范围
M ≤ 1000,n≤1000
样例输入
1
3 4 4
1 4
2 3
3 2
3 1
样例输出
Test case 1: 5
解题思路
线段树水题!
对于一条边,以L为第一关键字,r为第二关键字排序,求r的逆序对个数。
还有就是会爆int。虽然这很显然。
代码
#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
using namespace std;
namespace IStream{const int LLL=1<<15;char buffer[LLL],*SSS,*TTT;char Get_Char(){if(SSS==TTT){TTT=(SSS=buffer)+fread(buffer,1,LLL,stdin);if(SSS==TTT) return EOF;}return *SSS++;}int Getint(){char c;int re=0,f=1;for(c=Get_Char();c<'0'||c>'9';c=Get_Char())if(c=='-')f=-1;while(c>='0'&&c<='9')re=(re<<1)+(re<<3)+(c-'0'),c=Get_Char();return re*f;}}class OStream{private:static const int LLL=1<<15;char staack[21];int topp;char buffer[LLL],*SSS;public:OStream(){SSS=buffer;}void Putint(int x,int flag){bool fl=false;if(flag==1) staack[++topp]=' ';if(flag==2) staack[++topp]='\n';if(x<0) x=-x,fl=true;if(!x) staack[++topp]='0';while(x)staack[++topp]=x%10+'0',x/=10;if(fl)staack[++topp]='-';while(topp){if(SSS==buffer+LLL-1){fwrite(buffer,1,SSS-buffer,stdout);SSS=buffer;}*SSS++=staack[topp--];}}~OStream(){fwrite(buffer,1,SSS-buffer,stdout);*SSS=0;}}os;
#ifndef ONLINE_JUDGE
inline int Getint(){int x=0,f=1;char ch=getchar();while('0'>ch||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while('0'<=ch&&ch<='9'){x=x*10+ch-'0';ch=getchar();}return x*f;}
#else
using namespace IStream;
#endif
struct node{
int L,r;
}w[1000005];
struct Seg{
int L,r,Sum;
}Tree[400040];
bool cmp(node a,node b){
return a.L<b.L||(a.L==b.L&&a.r<b.r);
}
void Build(int v,int L,int r){
Tree[v]=(Seg){L,r,0};
if(L==r)return;
Build(2*v,L,(L+r)/2);
Build(2*v+1,(L+r)/2+1,r);
}
int Ask(int v,int vl){
if(Tree[v].r<vl)return 0;
if(vl<=Tree[v].L)return Tree[v].Sum;
return Ask(2*v,vl)+Ask(2*v+1,vl);
}
void Insert(int v,int vl){
if(vl<Tree[v].L||Tree[v].r<vl)return;
Tree[v].Sum++;
Insert(v*2,vl);
Insert(v*2+1,vl);
}
int main(){
int Case=Getint();
for(int orz=1;orz<=Case;orz++){
int L=Getint(),r=Getint(),k=Getint();
long long Ans=0;
for(int i=1;i<=k;i++)w[i]=(node){Getint(),Getint()};
sort(w+1,w+k+1,cmp);
Build(1,1,1005);
for(int i=1;i<=k;i++){
Ans+=Ask(1,w[i].r+1);
Insert(1,w[i].r);
}
cout<<"Test case "<<orz<<": "<<Ans<<"\n";
}
return 0;
}