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;
}
相关推荐
蓝悦无人机2 小时前
C++基础 — 函数总结
开发语言·c++
我不是懒洋洋4 小时前
从零实现一个分布式监控:Prometheus的核心设计
c++
An_s4 小时前
c++对接pdfium(一)win系统篇
开发语言·c++
众少成多积小致巨4 小时前
C++ 规范参考(上)
c++
猿的天空5 小时前
机器人双手迎来全栈训练系统:灵初智能EgoSteer让灵巧手无所不能
网络·人工智能·计算机·ai·程序员·机器人·编程
一拳一个呆瓜8 小时前
【STL】iostream 编程:使用提取运算符
c++·stl
我不是懒洋洋9 小时前
从零实现一个分布式日志平台:ELK的核心设计
c++
闻缺陷则喜何志丹9 小时前
【计算几何 第四章】线性规划:铸模制造
数学·计算几何·线性规划·铸造
神仙别闹9 小时前
基于QT(C++)实现Windows 自启动项查看和分析
c++·windows·qt
WWTYYDS_66610 小时前
ProtoBuf超详细使用教程
c++