题目大意就是:东部西部有两个岛,岛上分别有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); } }当!就是这样!