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; }
简简单单三个循环~前缀后缀的思想
BUT!!!!!!!!!!!!!!!
还有个方法!!!!!!!!!!!!
是博主shuaihui写的,
最后一个for循环里的判断:
如果最大的左端点/最小的右端点现在和我们枚举准备(删掉)的那个线段端点重合了,那么就把那个左端点变成第二大的/右端点变成第二小的/有了这个方法,我们还可以考虑,求一下n-m条线段重合的最大交集
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,这样~
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。