离散化所有的点,那么所有的航线只有三种情况
即垂直于河道,捺,撇。这三种情况分别记为 0,1,2
那么处理出所有相交的航线的集合,对于每一个集合,它对答案的贡献就是 0,1,2 中出现次数最多的那个次数。
代码如下,求大佬指出思路错误。
#include<bits/stdc++.h>
using namespace std;
int n;
const int N=1e6+6;
struct node{ int u,v,t; } a[N];
int b[N],c[N];
int belu[N],belv[N];
int bel[N],scc;
bool vis[N];
vector<int> member[N];
int ans;
bool cmp(node x,node y) { return x.u<y.u||(x.u==y.u&&x.v<y.v); }
bool check(int x,int y) { return a[x].u!=a[y].u && a[x].v!=a[y].t && a[x].t!=a[y].t; }
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i].u>>a[i].v;
sort(a+1,a+n+1,cmp);
for(int i=1;i<=n;i++) b[i]=a[i].u,c[i]=a[i].v;
sort(b+1,b+n+1); sort(c+1,c+n+1);
for(int i=1;i<=n;i++){
a[i].u=lower_bound(b+1,b+n+1,a[i].u)-b;
a[i].v=lower_bound(c+1,c+n+1,a[i].v)-c;
belu[a[i].u]=i; belv[a[i].v]=i;
}
for(int i=1;i<=n;i++){
if(a[i].u==a[i].v) a[i].t=0;
else if(a[i].u<a[i].v) a[i].t=1;
else a[i].t=2;
}
for(int i=1;i<=n;i++){
if(vis[i]) continue;
++scc;
if(!a[i].t) member[scc].push_back(i);
else {
if(a[i].t&1){
for(int x=a[i].u;x<=a[i].v;x++){
if(vis[belu[x]]) continue;
if(check(i,belu[x])){
vis[belu[x]]=true;
member[scc].push_back(belu[x]);
}
}
}
else {
for(int x=a[i].v;x<=a[i].u;x++){
if(vis[belv[x]]) continue;
if(check(i,belv[x])){
vis[belv[x]]=true;
member[scc].push_back(belv[x]);
}
}
}
}
}
for(int i=1;i<=scc;i++){
int cnt[3]={0,0,0};
for(int u:member[scc]) cnt[a[u].t]++;
ans+=max(max(cnt[0],cnt[1]),cnt[2]);
}
cout<<ans;
return 0;
}