Line

### Description

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

  

Solution

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

\[\begin{aligned} l_i&<=a_0-i\cdot d<=r_i\\ l_i+i\cdot d&<=a_0<=r_i+i\cdot d\\ \end{aligned} \]

​  然后我们建立一个横轴表示\(d\),纵轴表示\(a_0\)的坐标系,那么\(l_i+i\cdot d\)\(r_i+i\cdot d\)就可以看成半平面,\(l_i+i\cdot d\)取上方的,\(r_i+i\cdot d\)取下方的,然后我们预处理出所有\(r_i+i\cdot d\)交出来的一个“上凸壳”和\(l_i+i\cdot 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\n",ans);
}
posted @ 2018-12-27 20:17  yoyoball  阅读(124)  评论(0编辑  收藏