解決
これは面白いマップ構築の問題ああです。
まず、我々は、厳密に増加幅は全く使用しないことを見つけることができます。
実際に私たちが完了した後、回転しているので、
順序が容易矩形列であってもよいです。
ラインの幅は限り互いに大きく異なります。
私たちは、その後、各値の離散的な長さと幅は、ポイントを構築します。
含めるような例を見てみましょう:
最初のサンプルがリリース:
3
5 16
10 5
5 10
そして、(それは離散がなかったことを確認するのは簡単ですので)。ビル地図:
次に、各長さ、幅\(B \)矩形、
私たちは(A、B \)\でもサイドルーム。
だから、これはサブサブ図になりました:
二つの長方形があるので\((5,10)\)ので、2つの側面があります。
次に、エッジの幅の方向が長い定義します。
ここで長方形のもう一方の側に隣接する幅を意味し、長い答えはへの寄与であります
だから、指向回転矩形は、エッジとなりました。
その後、サイドには以下の特性を明らかにした後でも。
ポイントまでの各。
広い異なるため、それぞれ数アップが広いを行うことを確実にするためにするためです。
エッジの数\(m個\)以下の点\(N- \) 。
各辺がエッジのポイントとなっている必要がありますので、それを理解する感性は、あなたはその1の性質を証明することができます。
セット\(Iは\)点のうちで\(D [I] \) 、値\(ヴァル[I] \)の各点の次に寄与少なくとも\((D [I] -1 )* ヴァル[I] \) 。
各エッジは、各点で最も一度幅もあれば、または広い点を表し、そしてためです。
私たちは、その後、各分析通信ブロックを、
エッジの数は明らかに木環である点の数に等しい場合、
したがって、通信ブロックは上の点に寄与した(\ \ SUMの\のlimits_i(D [I] -1)*ヴァル[I] \) 。
エッジ点の数がマイナス1に等しい場合、それは、木であろう
ルートノードは、それの0アウトがありますが。
ライン上にルートをとる権利として私たちの最大値点限り、。
従って寄与\(\和の\ limits_i(D [I] -1)*ヴァル[I])+ \最大の\ limits_i(ヴァル[I])\)
各ブロックは、ライン上のDFSの統計情報と通信します。
しかし、不思議な操作があり、
通信ブロックのために、我々は設定\を(SUM = \ SUM \のlimits_i(D [I] -2)\) 、
場合は\(SUM <0 \) 、これは木です。
私たちがするポイントを設定しているので(N-を\)\、
辺の数\(\ FRAC。1} {2} {\ SUM \ limits_id [I] \) (偶数側は双方向であるため)。
而\(SUM = \和\ limits_id [I] -2n \)
ポイントを保存することは、エッジ* 2の数に等しいです。
そして、我々は(2 *それほど気にしない)ラインの大きさを比較するだけで済みます。
コード:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <map>
#define ll long long
#define fre(x) freopen(x".in","r",stdin),freopen(x".out","w",stdout)
using namespace std;
inline int read(){
int sum=0,f=1;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
return f*sum;
}
const int N=500001;
struct edge{int to,next;}e[N<<1];
int n,maxn,sum,ind[N],v[N];
int head[N],cnt=0;
int val[N],tot=0;
ll ans;
map <int,int> mp;
inline void add(int x,int y){
ind[y]++;e[++cnt]=(edge){head[x],y};head[x]=cnt;
}
inline void dfs(int x){
if(v[x]) return ;v[x]=1;
ans+=1ll*(ind[x]-1)*val[x];sum+=ind[x]-2;maxn=max(maxn,val[x]);
for(int i=head[x];i;i=e[i].to) dfs(e[i].next);
}
int main(){
n=read();
for(int i=1;i<=n;i++){
int x=read(),y=read();
if(!mp[x]){mp[x]=++tot;val[tot]=x;}
if(!mp[y]){mp[y]=++tot;val[tot]=y;}
x=mp[x];y=mp[y];
add(x,y);add(y,x);
}
for(int i=1;i<=tot;i++){
if(v[i]) continue;
maxn=sum=0;
dfs(i);
if(sum<0) ans+=maxn;
}
printf("%lld\n",ans);
return 0;
}