poj3067(树状数组)
题意:日本计划在东边的城市和西边的城市中建路,东边的点从1.....n,西边的点从1..........m,求这些点连起来后有多少交叉......
思路:一开始看到这个题目,完全没有思路。想了一下,把图画出来后,发现.....原来是树状数组的题目。
反思:这道题目思路很简单,但是我还是wa了3次,因为我没有将和定义为int64位......以前做树状数组题,也有好几次因为这个问题wa的,以后对于sum,一律将其赋值为64位的........................
#include<iostream>
#include<algorithm>
using namespace std;
#define max 1000005
struct node
{
int a,b;
}t[max];
int cmp(node &p,node &q) //对东边的城市进行升序排序,当东边为同一个点时,对西边的点进行升序排序,然后就是求逆序数了
{
if(p.a<q.a)
return 1;
else if(p.a==q.a&&p.b<q.b)
return 1;
else
return 0;
}
int c[max],n,m;
int lowbit(int x)
{
return x&(-x);
}
void updata(int i,int j)
{
while(i<=m)
{
c[i]+=j;
i+=lowbit(i);
}
}
__int64 getsum(int x)
{
__int64 sum=0;
while(x>0)
{
sum+=c[x];
x-=lowbit(x);
}
return sum;
}
int main()
{
int text,j=0;
scanf("%d",&text);
while(text--)
{
int k,i;
memset(c,0,sizeof(c));
scanf("%d%d%d",&n,&m,&k);
for( i=1;i<=k;i++)
{
scanf("%d%d",&t[i].a,&t[i].b);
}
sort(t+1,t+1+k,cmp);
__int64 sum=0;
//for(i=1;i<=k;i++)
// printf("%d %d\n",t[i].a,t[i].b);
for( i=1;i<=k;i++)
{
updata(t[i].b,1);
sum+=i-getsum(t[i].b);
}
printf("Test case %d: %I64d\n",++j,sum);
}
return 0;
}
朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。

浙公网安备 33010602011771号