1. 程式人生 > >poj-3067(樹狀陣列)

poj-3067(樹狀陣列)

題目連結:傳送門

題意:日本有東城m個城市,西城m個城市,東城與西城相互連線架橋,判斷這些橋相交的次數。

思路:兩個直線相交就是(x1-x2)*(y1-y2)<0,所以,對x,y進行排序,按照x從小到大進行排序,x相同,按照y從小到大排序

然後x已經有序,判斷y的逆序數。從大到小判斷,因為如果從小到大(3,1)與(3,2)就算相交,從大到小可以避免這種情況。

注意:

(1)陣列要開大一點;

(2)ans要用longlong型別,結果會很大。

#include<iostream>
#include<cstdio>
#include<cstring>
#include
<algorithm> using namespace std; const int maxn = 1200; int c[maxn],m,n; struct Node{ int x,y; }cur[maxn*maxn]; bool cmp(Node a,Node b) { if(a.x==b.x) return a.y<=b.y; else return a.x<b.x; } int lowbit(int x) { return x&(-x); } void update(int x,int Item) { while(x<=m) { c[x]
+=Item; x+=lowbit(x); } } int query(int x) { int sum=0; while(x>0) { sum+=c[x]; x-=lowbit(x); } return sum; } int main(void) { int i,j,T,k,x,y; scanf("%d",&T); for(i=1;i<=T;i++) { memset(c,0,sizeof(c)); scanf("%d%d%d
",&n,&m,&k); for(j=1;j<=k;j++) scanf("%d%d",&cur[j].x,&cur[j].y); sort(cur+1,cur+k+1,cmp); long long ans=0; for(j=1;j<=k;j++) { update(cur[j].y,1); ans+=(query(m)-query(cur[j].y)); } printf("Test case %d: %lld\n",i,ans); } return 0; }
View Code