poj 3067 树状数组

本文介绍了一种利用线段树统计区间相交数量的算法,通过将线段按左端点降序排列,并使用线段树统计每个线段与其他线段的交点数,从而高效解决区间相交问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

    这题的关键是方法。怎么才是相交的呢?一种方法是线段a的左边比线段b的左边小,同时a的右边比b的右边大。这时就可以构成一个相交。于是,我们可以根据左边的值来做降序排列,然后根据线段树来统计crosses。

排名还在上升中。加油!

#include <iostream>
#include <cstdio>
#include <fstream>
#include <algorithm>
#include <memory.h>

#define MAXN 1005
using namespace std;

int M,N,K;

int C[MAXN];
struct Node{
int n,m;
}nn[MAXN*MAXN];

bool cmp(Node a,Node b){
if(a.m==b.m) return a.n>b.n; //避免同端点的也算进去。
else return a.m>b.m;
}
inline int lowbit(int i){
return i&(-i);
}

void add(int i){
for(;i<MAXN ;C[i]+=1,i+=lowbit(i));
}

long long sum(int i){
long long s=0;
for(;i>0 ;s+=C[i],i-=lowbit(i));
return s;
}

int main()
{
int Case;
long long nSum;
int i,j,x;
//freopen("acm.in","r",stdin);
scanf("%d",&Case);
for(i=0 ;i<Case ;i++){
nSum=0;
memset(C, 0, sizeof(C));
scanf("%d%d%d",&N,&M,&K);
for(j=0 ;j<K ;j++)
scanf("%d%d",&nn[j].n,&nn[j].m);
sort(nn,nn+K,cmp);
for(x=0 ;x<K ;x++){
nSum+=sum(nn[x].n-1); //这里加的是右边比它大而左边比它小的那些线与它的焦点
//减一是为了避免左边的端点相同而多加一次。
add(nn[x].n); //这两个执行的顺序时关键
}
printf("Test case %d: %lld\n",i+1,nSum);
}
return 0;
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值