Test case (case number): (number of crossings)
题目大意就是:东部西部有两个岛,岛上分别有N个城市和M个城市,现在修建高速公路,求交点数。
解题方法:树状数组、逆序列。
谈谈这道题的体会:
在刚刚弄懂Lowbit(x)的神奇之处,迫不及待的准备小试身手,于是遇到了这道题。
(传送门Lowbit(t)https://www.cnblogs.com/hsd-/p/6139376.html
http://www.cnblogs.com/dilthey/p/6804136.html )
刚开始的时候思路一点也不清晰,甚至是不理解这道题和树状数组有什么关系。只是稿纸上画图找寻规律。
根据题意我们可以将题目化简,考虑一下题目的转折点->就是什么时候会出现交点。经过思考可以发现,在N是升序排列的前提之下,我现在讨论的(假设是第k组数据) 只要存在a[k].M 小于 a[1].M~a[k-1].M中的数就会有交点,且有几个小于就有几个交点。由此我们便可以想到用树状数组(既每次放入的点有可能会影响到之后输出的结果。因为对树状数组的领悟很浅所以想了半天他们之间联系,写了一大张演草纸==)来储存a[MAX_K].M的信息,最后再用逆序列的思想就可解决啦。
上代码
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define lowbit(x) (x)&(-x)
typedef long long ll;
int T,N,M,K;
ll c[1005];
struct node
{
int N,M;
}a[1005*1005];
bool cmp(node a,node b )
{
if(a.N==b.N) return a.M<b.M;
return a.N<b.N;
}
ll sum(int a)
{
ll ans=0;
for(int i=a;i>0;i-=lowbit(i)){
ans+=c[i];
}
return ans;
}
void add(int a)
{
while(a<=M){
c[a]=c[a]+1;
a+=lowbit(a);
}
}
int main()
{
scanf("%d",&T);
int t=1;
while(T--)
{
scanf("%d%d%d",&N,&M,&K);
for(int i=1;i<=K;i++){
scanf("%d%d",&a[i].N,&a[i].M);
}
sort(a+1,a+1+K,cmp);
memset(c,0,sizeof(c));
ll res=0;
for(int i=1;i<=K;i++)
{
add(a[i].M);
// cout<<sum(a[i].M)<<endl;
res+=(i-sum(a[i].M));//逆序列思想
//cout<<sum<<endl;
}
printf("Test case %d: %I64d\n",t++,res);
}
}
当!就是这样!