Codeforces Round #506 (Div. 3)
作者:互联网
STL算什么!!!还是那句话!!!
数组模拟世间万物!!!!!!!!!!!!!!!!!
好吧,前缀后缀方法&stl法
前缀后缀:
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define s second
#define f first
const int N = 1e6;
const int INF = 1e9;
int ans = 0;
pair<int,int> a[N], pre[N], suf[N];//prefix前缀,suffix后缀
int32_t main(){
ios_base::sync_with_stdio(0);
cin.tie(0);
int n;cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i].f>>a[i].s;
pre[0].f=suf[n+1].f=0;//等会用于比大小的
pre[0].s=suf[n+1].s=INF;//等会用于比大小的
for(int i=1;i<=n;i++){
pre[i].f=max(pre[i-1].f,a[i].f);//表示前i个数中,最大的左端点的坐标
pre[i].s=min(pre[i-1].s,a[i].s);//表示前i个数中,最小的右端点的坐标
}
for(int i=n;i>=1;i--){
suf[i].f=max(suf[i+1].f,a[i].f);//表示从第i个数到第n个数中,最大的左端点的坐标
suf[i].s=min(suf[i+1].s,a[i].s);//表示从第i个数到第n个数中,最小的右端点的坐标
}
for(int i=1;i<=n;i++){
int l=max(pre[i-1].f,suf[i+1].f);//除去第i个线段后,最大的左端点的坐标
int r=min(pre[i-1].s,suf[i+1].s);//除去第i个线段后,最小的右端点的坐标
ans = max(ans, r - l);
}
cout << ans;
//system("pause");
return 0;
}
简简单单三个循环~前缀后缀的思想,不必多说
STL方法
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5 + 10;
const int INF = int(1e9);
#define int long long
multiset<int>a, b;
int n, l[N], r[N],ans,ans1;
int32_t main(){
cin >> n;
for(int i=0;i<n;i++){
cin >>l[i] >> r[i];
a.insert(l[i]);
b.insert(r[i]);
}
for (int i = 0; i < n;i++){
a.erase(a.find(l[i]));
b.erase(b.find(r[i]));
ans = max(ans, *b.begin() - *a.rbegin());
a.insert(l[i]);
b.insert(r[i]);
}
cout << ans;
//system("pause");
return 0;
}
这个题用STL耗时真的是太长了
感觉怕怕的
跟上面的思路是一样的,
因为我们求交集的方法就是
右端点的最小值-左端点的最大值
然后现在就是排除每一个线段,算交集,就这么一趟求下来
multiset自带排序功能,很方便
但是注意一个问题
a.erase(a.find(l[i]));
a.erase(l[i]);
这两者是不一样的,后者会把所有的这个数值的数全都删掉,set也是这样,但是这道题的情景是
每次删除一条线段,看看剩下n-1条的交集是谁
所以必须要用上面的方法,只删除那一个,multiset里面可以包含好多相同的元素,也会排序
比如1,2,3,4,4,4,4,4,4,这样~
标签:suf,const,insert,int,Codeforces,long,erase,506,Div 来源: https://www.cnblogs.com/guaguastandup/p/10356064.html