POJ 3067 Japan (树状数组)

题意:顺序给两组平行的点依次编号1~N和1~M,给定K个线段在两组点之间,求相交(cross)的线段对有多少个,同一个起点或终点不算相交。

思路:由于题目涉及到统计和的问题,自然可以交给树状数组来做,方法和Cows差不多现对线段进行排序,按w由大到小,如果w相等,按e从大到小(必要),最后遍历,修改查询就可以了。

 

  
    
#include < iostream >
#include
< cstdio >
#include
< algorithm >
#include
< memory.h >
#include
< cmath >
#include
< bitset >
#include
< queue >
#include
< vector >
using namespace std;

const int BORDER = ( 1 << 20 ) - 1 ;
const int MAXSIZE = 37 ;
const int MAXN = 1100 ;
const int INF = 1000000000 ;
#define CLR(x,y) memset(x,y,sizeof(x))
#define ADD(x) x=((x+1)&BORDER)
#define IN(x) scanf("%d",&x)
#define OUT(x) printf("%d\n",x)
#define MIN(m,v) (m)<(v)?(m):(v)
#define MAX(m,v) (m)>(v)?(m):(v)
#define ABS(x) ((x)>0?(x):-(x))

typedef
struct {
int e,w;
}Node;

Node node[MAXN
* MAXN];
__int64 tre[MAXN];
int n,m,k,n_tre,t_case;
__int64 ans;

bool cmp( const Node & a, const Node & b)
{
if (a.w == b.w)
return a.e > b.e;
return a.w > b.w;
}
int lowbit( int x)
{
return x & ( - x);
}
void modify( int ind, const int & delta)
{
for ( ; ind <= n_tre; ind += lowbit(ind))
tre[ind]
+= delta;
}
__int64 get_sum(
int ind)
{
int sum = 0 ;
for ( ; ind != 0 ; ind -= lowbit(ind))
sum
+= tre[ind];
return sum;
}
int init()
{
ans
= 0 ;
CLR(tre,
0 );
n_tre
= 1023 ;
return 0 ;
}
int input()
{
scanf(
" %d%d%d " , & n, & m, & k);
n_tre
= m + 1 ;
for ( int i = 0 ; i < k; ++ i)
{
scanf(
" %d%d " , & node[i].w, & node[i].e);
++ node[i].e;
}
return 0 ;
}
int work()
{
int i,j,tmp;
sort(node,node
+ k,cmp);
for (i = 0 ; i < k; ++ i)
{
ans
+= get_sum(node[i].e - 1 );
modify(node[i].e,
1 );
}
printf(
" Test case %d: " ,t_case ++ );
cout
<< ans << endl;
return 0 ;
}
int main()
{
int t;
t_case
= 1 ;
IN(t);
while (t -- )
{
init();
input();
work();
}
return 0 ;
}

 

 

你可能感兴趣的:(树状数组)