zoukankan      html  css  js  c++  java
  • 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);
    }
    
  • 相关阅读:
    POJ
    POJ
    BZOJ
    HDU
    codeforces
    BZOJ
    SPOJ
    SPOJ
    SPOJ
    HDU
  • 原文地址:https://www.cnblogs.com/yoyoball/p/10187087.html
Copyright © 2011-2022 走看看