空【NOIP2017提高A组模拟8.24】
程序员文章站
2023-12-24 22:09:27
...
题目
输入
输出
Sample Input
3
10 100
1 50
50 100
Sample Output
99
数据范围
思路
比赛时忘记包含的情况,导致样例过不了,心跳炸了。
解法
设有两条线段i,j。用l与r表示左右端点。
首先按找l排序。
分两种情况:
1.i,j是相交的。
ans=r[j]-l[i]-(r[i]-l[j])=-(r[i]+r[j])-(l[i]+l[j])。
这种情况下,是与l+r的值有关。
2.i,j是包含的。
ans=r[i]-l[i]-(r[j]-l[j])。这种情况下与r-l有关。
一个数据结构,维护r+l的最大值与r-l的最小值+一根扫描线。
时间O(n log n)。
代码
#include<cstdlib>
#include<cstring>
#include<cstdio>
#include<cmath>
#include<algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
using namespace std;
const int maxn=2e5+5;
struct cy{
int l,r,sum,del;
}a[maxn];
struct hg{
int val,r;
}hs[maxn*2],hd[maxn*2];
int n,ans,ansmin,ansmax,nums,numd;
int read()
{
int x=0; char c;
for(c=getchar();c<'0'||c>'9';c=getchar());
for(c;c>='0'&&c<='9';c=getchar()) x=x*10+c-48;
return x;
}
bool cmp(cy a,cy b)
{
return a.l<b.l||a.l==b.l&&a.r>b.r;
}
void downmin(int x)
{
while (hs[x<<1].val<hs[x].val||hs[x<<1|1].val<hs[x].val){
if (hs[x<<1].val<hs[x<<1|1].val){
swap(hs[x<<1].val,hs[x].val);
swap(hs[x<<1].r,hs[x].r);
x=x<<1;
}
else {
swap(hs[x<<1|1].val,hs[x].val);
swap(hs[x<<1|1].r,hs[x].r);
x=x<<1|1;
}
}
}
void downmax(int x)
{
while (hd[x<<1].val>hd[x].val||hd[x<<1|1].val>hd[x].val){
if (hd[x<<1].val>hd[x<<1|1].val){
swap(hd[x<<1].val,hd[x].val);
swap(hd[x<<1].r,hd[x].r);
x=x<<1;
}
else {
swap(hd[x<<1|1].val,hd[x].val);
swap(hd[x<<1|1].r,hd[x].r);
x=x<<1|1;
}
}
}
void upmin(int x)
{
while (hs[x>>1].val>hs[x].val) {
swap(hs[x>>1].val,hs[x].val);
swap(hs[x>>1].r,hs[x].r);
x>>=1;
}
}
void upmax(int x)
{
while (hd[x>>1].val<hd[x].val) {
swap(hd[x>>1].val,hd[x].val);
swap(hd[x>>1].r,hd[x].r);
x>>=1;
}
}
int main()
{
//freopen("T.in","r",stdin);
n=read();
fo(i,1,n){
a[i].l=read(),a[i].r=read();
a[i].sum=a[i].l+a[i].r;
a[i].del=a[i].r-a[i].l;
}
sort(a+1,a+n+1,cmp);
memset(hs,127,sizeof(hs));
hs[0].val=0; hd[0].val=1e9+50;
hs[0].r=1e9; hd[0].r=1e9;
hs[++nums].val=a[1].sum,hs[nums].r=a[1].r;
hd[++numd].val=a[1].del,hd[numd].r=a[1].r;
int now;
fo(i,2,n){
now=0;
while (hs[1].r<a[i].l){
hs[1].val=hs[nums].val;
hs[1].r=hs[nums].r;
hs[nums].val=1e9; hs[nums--].r=1e9;
downmin(1);
}
now=hs[1].val;
if(now) ans=max(ans,a[i].sum-now);
while (hd[1].r<a[i].l){
hd[1].val=hd[numd].val;
hd[1].r=hd[numd].r;
hd[numd].val=0; hd[numd--].r=1e9;
downmax(1);
}
now=hd[1].val;
if (now) ans=max(now-a[i].del,ans);
hs[++nums].val=a[i].sum; hs[nums].r=a[i].r;
hd[++numd].val=a[i].del; hd[numd].r=a[i].r;
upmin(nums);
upmax(numd);
}
printf("%d\n",ans);
}