1. 程式人生 > >POJ 3067 Japan (樹狀數組 && 控制變量)

POJ 3067 Japan (樹狀數組 && 控制變量)

AD struct \n UC 多少 i++ gif hid %d

題意: 西海岸和東海岸有分別有n (1~n)個和m (1~m)個城市, 兩個海岸的城市之間有k條公路連通, 公路會相交, 現在給出城市和公路的信息問你由這些公路組成的復雜交通有多少個交點 (如果兩個條公路的起點或者終點相同那這兩點不算做相交)

分析:先分析題目案例可以知道當y1>y2時,這樣是肯定會有交點的。可以根據這個特性很快就可以發現這個就是個求逆序對的問題。但是又是不完全的正確,因為這樣分析出來的答案是6,結果錯誤。現在在來分析是哪裏出現的錯誤,是(3,1)與(3,2)這裏的問題,分析題目可知到,如果起點或者終點相同那就不算是香蕉,所以可以得出結論,如果x相等的時候,逆序對不存在,即將y的值對調。同時我們又可以發現前面的這些性質都是在x按升序的情況下成立,所以現在問題的解決就很簡單了,按x升序排,相等的話按照y升序排,然後在求得逆序對。

技術分享圖片
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string>
#include<string.h>
#include<set>
#define LL long long
#define lowbit(i) (i&(-i))
using namespace std;
int c[1001], n, k, m;
void add(int i, int val)
{
    while(i<=m){
        c[i] += val;
        i 
+= lowbit(i); } } LL sum(int i) { LL ans = 0; while(i>0){ ans += c[i]; i -= lowbit(i); } return ans; } struct no { int x, y; }arr[10000000]; bool cmp(const no fir, const no sec) { if(fir.x == sec.x) return fir.y < sec.y; return fir.x < sec.x; } int main(void
) { int nCase; scanf("%d", &nCase); for(int t=1; t<=nCase; t++){ memset(c, 0, sizeof(c)); scanf("%d%d%d", &n, &m, &k); for(int i=0; i<k; i++){ scanf("%d%d", &arr[i].x, &arr[i].y); } sort(arr, arr+k, cmp); LL ans = 0; for(int i=0; i<k; i++){ ans += i - sum(arr[i].y); add(arr[i].y, 1); } printf("Test case %d: %lld\n", t, ans); } return 0; }
View Code

POJ 3067 Japan (樹狀數組 && 控制變量)