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;
}
相关推荐
喵星人工作室1 小时前
C++火影忍者1.1.8
开发语言·c++·游戏
凡人叶枫1 小时前
Effective C++ 条款26:尽可能延后变量定义式的出现时间
linux·开发语言·c++·effective c++
加油码1 小时前
位图 BitMap:用一个 bit 管一个状态,空间直接省到位
c++·算法
四代水门1 小时前
LeetCode刷算法题(C++)
c++·算法·leetcode
unicrom_深圳市由你创科技10 小时前
哪些控制逻辑应该放在 PLC,哪些放在上位机?
c++
玖玥拾12 小时前
C/C++ 基础笔记(十三)继承
c语言·c++·继承
ao-weilai13 小时前
C++:哈希表
c++·哈希算法·散列表
汉克老师13 小时前
GESP7级C++考试语法知识(二、指数函数(1、pow() 函数)
c++·指数函数·pow·gesp7级·精度误差
旖-旎13 小时前
FloodFill(图像渲染)(1)
c++·算法·深度优先·力扣