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; }
朋友们,虽然这个世界日益浮躁起来,只要能够为了当时纯粹的梦想和感动坚持努力下去,不管其它人怎么样,我们也能够保持自己的本色走下去。