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;
}
原文地址:https://www.cnblogs.com/lvpengms/p/1719140.html