ABC462D 题解

ABC462D 题解

link.

题目描述

给定 n n n 个区间 l , r l,r l,r,求有多少个 s , i , j s,i,j s,i,j 满足 s , s + d s,s+d s,s+d l i , r i l j , r j l_i,r_i\cap l_j,r_j li,rilj,rj 包含,其中 1 ≤ i < j ≤ n 1\le i<j\le n 1≤i<j≤n。

数据范围请自己看题目。

思路

首先对所有区间进行排序是显然的。以 l l l 为第一关键字,以 r r r 为第二关键字从小到大排。

然后我们发现枚举两个区间的时间复杂度是 O ( n 2 ) O(n^2) O(n2) 的,直接爆炸。

观察一下发现所有区间左右端点的取值范围才 10 6 10^6 106,所以考虑枚举开始作案的时间 s s s。

所以我们可以找到最后一个 满足 l k < s l_k<s lk<s 的区间 k k k,那么包含 s , s + d s,s+d s,s+d 的区间一定是从 1 ∼ k 1\sim k 1∼k 里面找。

给张图理解下。

由于我们的区间是按照 l l l 从小到大排序了,所以在 k k k 之前的区间的 l l l 一定也小于 s s s,也就是一定合法。

现在看怎么找 k k k。

然后注意到我们已经对所有区间排完序了,包含区间 s , s + d s,s+d s,s+d 的区间们在编号上一定也是个区间,且是整体的前缀。

而我们也是从小到大找 s s s 的,所以我们可以不断判断下一个区间的 l l l 是否小于 s s s,时间复杂度均摊 O ( 1 ) O(1) O(1),不懂看代码。

接下来在 1 ∼ k 1\sim k 1∼k 中的区间的左端点一定是合法的,所以只要看多少个右端点大等于 s + d s+d s+d 即可。这个可以用树状数组 O ( log ⁡ n ) O(\log n) O(logn) 求。

假设有 S S S 个区间的右端点大等于 s + d s+d s+d,那么对答案的贡献就是 ( S 2 ) = S ( S − 1 ) 2 \binom{S}{2}=\frac{S(S-1)}{2} (2S)=2S(S−1)。

代码

cpp 复制代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ljl;
const int N=2e5+5,M=1e6+5;
int n,cur;
ljl ans,mxr,trc[M],d;
int lowbit(int x){return x&(-x);}
ljl query(int x){
	ljl ans=0;
	for(;x>0;x-=lowbit(x))ans+=trc[x];
	return ans;
}
ljl querylr(ljl l,ljl r){return query(r)-query(l-1);}
void add(int x,ljl val)
{
	for(;x<=mxr;x+=lowbit(x))trc[x]+=val;
	return;
}
struct NODE{
	ljl l,r;
	bool operator < (const NODE a)const{
		if(l!=a.l)return l<a.l;
		return r<a.r;
	}
}node[N];
int main(){
	ios::sync_with_stdio(0);
	cin>>n>>d;
	for(int i=1;i<=n;++i)
	{
		cin>>node[i].l>>node[i].r;
		mxr=max(mxr,node[i].r);
	}
	sort(node+1,node+n+1);
	
	for(ljl st=1;st+d<=mxr;++st)
	{
		while(cur<n&&node[cur+1].l<=st)//这里的cur最多只会增加n次,所以复杂度均摊O(1)
		{
			++cur;
			add(node[cur].r,1ll);
//			cout<<"------\n"; 
		}
		ljl sum=querylr(st+d,mxr);
//		cout<<st<<": "<<sum<<'\n';
		ans=ans+(sum*(sum-1)/2);
	}
	cout<<ans<<'\n';
	return 0;
}
相关推荐
郝学胜_神的一滴3 小时前
CMake 037:宏传递流转机制与C++编译特性跨平台适配指南
c++·cmake
apocelipes2 天前
常用编程语言和库的正则表达式性能对比
c语言·c++·python·性能优化·golang·开发工具和环境
郝学胜_神的一滴3 天前
CMake 034:生成器表达式:解耦构建时序、精简分支逻辑的终极利器
c++·cmake
金銀銅鐵4 天前
[Python] 基于欧几里得算法,实现分数约分计算器
python·数学
见过夏天4 天前
C++ 基础入门完全指南
c++
小七-七牛开发者4 天前
论文解读:DeepSeek DSpark 在真实高并发推理服务中,如何保证 Token 生成又好又快?
ai·大模型·编程·ai coding
用户805533698035 天前
不止三件套:QObject 属性系统全关键字与运行时反射!
c++·qt
BadBadBad__AK6 天前
线段树维护区间 k 次方和
c++·数学·算法·stl
金銀銅鐵6 天前
[Python] 模 n 乘法的逆元计算器
python·数学·游戏
卷无止境6 天前
Eigen 库如何借助 OpenMP 加速计算
c++·后端