地址:
点击打开链接
很多时候树状数组都可以求在一个数之前的所有比他大的数,这个性质是不能忘的。
目前接触到的梳妆树的应用:
求和(区间求和),求第k大,再有就是上边这种。
逆序数只是一个概念,就是上面所阐述的:
求在一个数之前的所有比他大的数
#include<iostream >
#include<cstdio>
#include<string.h>
#include<algorithm>
using namespace std ;
#define MAX 50001
struct Node{
double l;
double r ;
int Num ;
}nodes[MAX];
int Rem[MAX];
bool cmpl (Node a , Node b)
{
if(a.l==b.l)
{
return a.r<b.r;
}
return a.l<b.l;
}
bool cmpr(Node a , Node b)
{
if(a.r == b.r)
{
return a.l>b.l;
}
return a.r>b.r;
}
int lowbit(int a)
{
return a&(-a);
}
void update(int index , int d)
{
for(int i = index ; i <MAX ; i+=lowbit(i))
{
Rem[i]+=d;
}
}
int getSum(int index)
{
int res =0 ;
for(int i = index ; i >0 ; i -=lowbit(i))
{
res += Rem[i];
}
return res ;
}
int main(){
double k ,b,l ,r ;
double ax,ay,bx,by;
int Num,i,j ;
int t , ret;
while(~scanf("%d",&Num))
{
scanf("%lf%lf",&l,&r);
t = 0;
ret = 0 ;
for(i = 0 ; i <Num ; i ++)
{
scanf("%lf%lf%lf%lf",&ax,&ay,&bx,&by);
if(ax == bx)
{
if(ax<r&&ax>l)
ret ++ ;
continue ;
}
k = (by-ay)/(bx-ax);
b = by-k*bx;
nodes[t].l=k*l+b;
nodes[t++].r=k*r+b;
}
sort(nodes,nodes+t ,cmpl);
for(i = 1 ; i <=t; i ++)
{
nodes[i-1].Num = i ;
}
sort(nodes,nodes+t ,cmpr);
memset(Rem,0,sizeof(Rem));
int sum_sum = 0;
for(i = 0 ; i < t ; i ++)
{
update(nodes[i].Num,1);
sum_sum += getSum(nodes[i].Num-1);
// printf("%d\n",sum_sum);
}
//printf("%d %d %d\n",sum_sum ,ret , t );
printf("%d\n",sum_sum+ret*t);
}
}