当前位置:编程学习 > C/C++ >>

POJ 3067 Japan 树状数组

题意:两边都有一些城市,从上到下排列,有些城市之间有路,路与路之间会形成交点,问最后会形成多少个交点。
思路:首先可以把有联系的城市转化成平面上的点,比如说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; 

 
补充:软件开发 , C++ ,
CopyRight © 2022 站长资源库 编程知识问答 zzzyk.com All Rights Reserved
部分文章来自网络,