传送门
大体思路就是:枚举所有可能的水平对称线,计算面积更新答案。
所有可能的水平对称线:(L_i,R_i,{L_i+R_iover 2})
计算面积:将所有可能的水平对称线从小到大排序,然后依次计算。
假设算出了第(i-1)条对称线的答案,然后更新第(i) 条的,两个的高度差为(h)
对于块1,贡献多了(2h),对块2并没有贡献。
当更新第(i+1)条时,高度差为(h_2),对块1的贡献为(2h_2),对块2的贡献为(2h_2)。
当更新第(i+2)条时,高度差为(h_3),对块1的贡献为(-2h_3),对块2的贡献为(2*h_3)
(cdots)
可以发现,如果枚举的对称线过了某个块的底线,那么这个贡献就是高度差的2倍,如果过了该块的对称线,贡献就是负的高度差的2倍,如果过了顶线,贡献为0。
所以要时刻记录以下两种块的数量差:
[已过底线但未过对称线 - 已过对称线但未过顶线
]
体现在程序中可以通过底线时,个数++,通过对称线时,个数-2,通过顶线++
另外可以先把高度都乘2,在计算过程中就不必再乘2了。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 300010;
typedef pair<int,int> pii;
vector<pii> v;
int n;
int main(){
scanf("%d",&n);Q
for(int i=1;i<=n;i++){
int x,y;
scanf("%d%d",&x,&y);
v.push_back({x+x,1});
v.push_back({x+y,-2});
v.push_back({y+y,1});
}
sort(v.begin(),v.end());
ll res = 0,sum = 0,last = 0,sz = 0;
for(auto x : v){
sum += sz * (x.first - last);
res = max(res,sum);
sz += x.second;
last = x.first;
}
cout<<res<<endl;
return 0;
}