程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> C++ >> C++入門知識 >> POJ 3067 Japan 樹狀數組

POJ 3067 Japan 樹狀數組

編輯:C++入門知識

題意:兩邊都有一些城市,從上到下排列,有些城市之間有路,路與路之間會形成交點,問最後會形成多少個交點。
思路:首先可以把有聯系的城市轉化成平面上的點,比如說1 和2 之間有一條路,則代表有一個點,坐標為(1,2)。轉化之後可以用樹狀數組做,可以發現最後的結果其實和所給的順序無關,因此我們可以按y軸從小到大排序,若y軸相等,則按x軸從大到小排。
代碼:
[cpp]  
#include <iostream> 
#include <cstdio> 
#include <algorithm> 
#include <string.h> 
using namespace std; 
 
#define CLR(arr,val) memset(arr,val,sizeof(arr)) 
typedef long long LL; 
const int N = 1010; 
LL num[N]; 
int flag[N][N]; 
struct road{ 
    int x,y; 
}rr[N*N]; 
bool cmp(road a,road b){ 
    if(a.y == b.y) 
        return a.x > b.x; 
    return a.y > b.y; 

int lowbit(int x){ 
    return x & (-x); 

void update(int x){ 
    while(x < N){ 
      num[x] += 1; 
      x += lowbit(x); 
    } 

LL add(int x){ 
    LL s = 0; 
    while(x > 0){ 
       s += num[x]; 
       x -= lowbit(x); 
    } 
    return s; 

int main(){ 
    //freopen("1.txt","r",stdin); 
    int numcase; 
    scanf("%d",&numcase); 
    int ca = 1; 
    while(numcase--){ 
       int n,m,k; 
       CLR(num,0); 
       CLR(flag,0); 
       scanf("%d%d%d",&n,&m,&k); 
       int x,y; 
       LL sum = 0; 
       for(int i = 0; i < k; ++i){ 
          scanf("%d%d",&rr[i].x,&rr[i].y); 
       } 
       sort(rr,rr+k,cmp); 
       for(int i = 0; i < k; ++i){ 
           if(flag[rr[i].x][rr[i].y]) 
               continue; 
          sum += add(rr[i].x - 1); 
          update(rr[i].x); 
          flag[rr[i].x][rr[i].y] = 1; 
       } 
       printf("Test case %d: %lld\n",ca++,sum); 
    } 
    return 0; 

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved