2 F. Greetings(离散化+树状数组)

题目链接

F. Greetings

题意

image

题解

由于两个人的速度是一样的,所以到达终点之前两个人是不会相遇的,考虑一下什么情况两个人会相遇,其中一个人到达终点时,另一个人,终点所在地的前面,并且它的终点在更右边。
将两个人的起点终点分别用 S a 、 S b 、 E a 、 E b S_a 、S_b、 E_a、 E_b SaSbEaEb表示,并假设 a a a在前 b b b在后(b在前是对称的),有下图

  1. a a a的终点 < < < b b b的终点,这时两者同时出发,a到终点时,b已经经过的a的终点,两者不会相遇,对答案没有贡献
    19bf509ef2070db7825b2eaddda78458.jpeg
  2. a a a的终点 > > > b b b的终点,这时b会先到终点,速度一样,a此时还没有到达 E b E_b Eb,此时两者一定会在 E b E_b Eb相遇
    0972e8479cc965d5b05e6802a33eebed.jpeg
    所以答案转化为对于当前区间计算有多少个区间被它所包含。

因为这道题目数据的实际大小是没有意义的,相对大小是有用的,并且值域比较大,我们考虑离散化,然后通过树状数组去查询。
具体的做法是,先按右端点从小打大排序,然后从前往后遍历区间,每次查询起点大于当前点起点的个数。就是这个区间对答案产生的贡献。

代码

#include <bits/stdc++.h>
#define int long long
#define rep(i,a,b) for(int i = (a); i <= (b); ++i)
#define fep(i,a,b) for(int i = (a); i >= (b); --i)
#define pii pair<int, int>
#define ll long long
#define db double
#define endl '\n'
#define x first
#define y second
#define pb push_back

using namespace std;

void solve() {
	int n;
	cin>>n;
	struct node{
		int l,r;
		bool operator<(const node &t)const{
			return r<t.r;
		}
	};
	vector<node>a(n);
	vector<int>b(2*n);
	int k=0;
	rep(i,0,n-1){
		cin>>a[i].l>>a[i].r;
		b[k++]=a[i].l;
		b[k++]=a[i].r;
	}
	sort(b.begin(),b.end());
	rep(i,0,n-1){
		a[i].l=lower_bound(b.begin(),b.end(),a[i].l)-b.begin()+1;
		a[i].r=lower_bound(b.begin(),b.end(),a[i].r)-b.begin()+1;
	}
	sort(a.begin(),a.end());
//	rep(i,0,n-1){
//		cout<<a[i].l<<' '<<a[i].r<<endl;
//	}
	vector<int>c(2*n+1,0);
	auto lowbit=[](int x){
		return x&-x;
	};
	
	auto add=[&](int x,int k)->void{
		for(int i=x;i<=2*n;i+=lowbit(i)){
			c[i]+=k;
		}	
	};
	
	auto sum=[&](int x){
		int res=0;
		for(int i=x;i;i-=lowbit(i)){
			res+=c[i];
		}	
		return res;
	};
	int ans=0;
	rep(i,0,n-1){
		int r=a[i].r,l=a[i].l;
		ans+=sum(r)-sum(l-1);
		add(l,1);
	}
	cout<<ans<<endl;
}

signed main() {
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
//	freopen("1.in", "r", stdin);
	int _;
	cin>>_;
	while(_--)
		solve();
	return 0;
}


总结

  1. 离散化的板子记得不是很熟,这种东西应该很熟并且默写的很快的
  2. 树状数组用的还是比较少有些细节记得不太清,就比如树状数组的下标是从几开始的?
    答案是1,这就导致离散化的时候也要从1开始。
  3. 看了一些题解,发现了这类问题被称为二维偏序问题
    a i < a j 、 b i > b j a_i<a_j、b_i>b_j ai<ajbi>bj

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值