Line

### Description

  数据范围:(2<=n<=2*10^5,1<=l_i<=r_i<=10^9)

  

Solution

  稍微想一下就大概是你确定下来(a_{i}-a_{i+1})的值(d),再确定下来开始(a_0),那么一条线就确定下来了,然后我们要满足:

[egin{aligned} l_i&<=a_0-icdot d<=r_i\ l_i+icdot d&<=a_0<=r_i+icdot d\ end{aligned} ]

​  然后我们建立一个横轴表示(d),纵轴表示(a_0)的坐标系,那么(l_i+icdot d)(r_i+icdot d)就可以看成半平面,(l_i+icdot d)取上方的,(r_i+icdot d)取下方的,然后我们预处理出所有(r_i+icdot d)交出来的一个“上凸壳”和(l_i+icdot d)交出来的一个“下凸壳”,中间围出来的部分中的整点数量就是答案(实现上的话。。因为斜率就是(i)已经排好序了所以直接求凸壳就好了)

  因为是整点,所以我们可以直接算面积就好了,具体就是从左往右扫“上下凸壳”,按照交出来的交点把中间的整个部分分成若干个梯形(两边可能是三角形),然后直接用公式计算面积然后加起来就好了

  

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const int N=2e5+10,inf=1e9;
struct Dot{
	int x,y;
	Dot(int x1=0,int y1=0){x=x1; y=y1;}
	friend ll crs(Dot a,Dot b){return 1LL*a.x*b.y-1LL*a.y*b.x;}
	friend Dot operator - (Dot a,Dot b){return Dot(a.x-b.x,a.y-b.y);}
	friend double inter_pot(Dot a,Dot b){return -(1.0*a.y-b.y)/(1.0*a.x-b.x);}
	ll val(ll x0){return 1LL*x*x0+y;}
}a[N*2];
Dot lst[N],rst[N];
int l[N],r[N];
int n,topl,topr;
ll ans;
int cmp(Dot x,Dot y,Dot z){
	return crs(y-x,z-x)>0?1:-1;
}

int main(){
#ifndef ONLINE_JUDGE
	freopen("a.in","r",stdin);
#endif
	scanf("%d",&n);
	for (int i=1;i<=n;++i){
		scanf("%d%d",l+i,r+i);
		a[i]=Dot(i,l[i]);
		a[i+n]=Dot(i,r[i]);
	}
	topl=0; topr=0;
	for (int i=1;i<=n;++i){
		while (topl>1&&cmp(lst[topl-1],lst[topl],a[i])==1) --topl;
		lst[++topl]=a[i];
		while (topr>1&&cmp(rst[topr-1],rst[topr],a[i+n])==-1) --topr;
		rst[++topr]=a[i+n];
	}
	int pl=1,pr=topr;
	ll edl,edr,st=-inf,ed;
	while (pl<=topl&&pr){
		edl=pl+1<=topl?floor(inter_pot(lst[pl],lst[pl+1])):inf;
		edr=pr-1?floor(inter_pot(rst[pr],rst[pr-1])):inf;
		ed=min(edl,edr);

		if (lst[pl].x<rst[pr].x) 
			st=max(st,(ll)ceil(inter_pot(lst[pl],rst[pr])));
		else if (lst[pl].x>rst[pr].x)
			ed=min(ed,(ll)floor(inter_pot(lst[pl],rst[pr])));

		if (st<=ed)
			ans+=1LL*(ed-st+1)*((rst[pr].val(st)-lst[pl].val(st)+1)+(rst[pr].val(ed)-lst[pl].val(ed)+1))/2;
		if (min(edl,edr)==edl) ++pl;
		else --pr;
		st=min(edl,edr)+1;
	}
	printf("%lld
",ans);
}
原文地址:https://www.cnblogs.com/yoyoball/p/10187087.html