本题折磨了本菜鸡一中午,菜鸡思路是列出所有可能出现的情况,有以下几种:
1. ————————————————
——————————————————
1 3
2 4
2. ——————————————
——————————————————————
1 3
0 4
3. ————————————————————— —————————
1 3
4 5
4. 1 3
3 6
5. ——————————————————————
————————————
0 3
1 2
会有两区间的这五种关系,其中除了第三种情况不能合并外,其余均可以,
我的思路是将这么几种情况依据t[i].second与t[i+1].first等之间的关系
列出这么几种情况进行判别,这样当然很麻烦而且不停的出bug,这也许就是
菜鸡和大佬之间的区别,不懂得怎么样将这些情况进行简化!!!呜呜
继续努力吧!
以下是我遇到的问题:
对于c的处理很是头疼,原本我写的是
for(int i=0;i<n;){
int q=t[i].second;
while(q>t[i+1].first&&i+1>n){
q=max(t[i+1].second,q);
i++;
}
c++;
* int q=t[i].second;
>>>>>
}
这样我遇到了很多问题,第一这样写会不会丢到某些区间,并且
如果一个集合只有一个区间时,这样c正确,但是如果两个区间,
并且不能合并就会出现问题当然当n>2时也存在各种各样的
问题,进行特判也不好整
另外就是while()循环的问题一直不能合并退出该循环,我下一个区间是
1 2 2 3 5 6
中的5 6的话跟c 间的关系也不好弄,问题在这里纠结了好久好久,我是个
废物。
并且我还惊奇的发现在*语句这里我再次int,q的值会出现问题,如果去掉
int 就没有问题,我不明白这里,?先打个小问号,等我成长这在思考
感悟:
_**先进行排序!!!!!**_
这道题应该把while循环改为if语句,将各个区间联系起来,其实两者的时间复杂度是一样的,
能用if就别用while 了,可以少考虑一些问题
这里c的起始值是1,而我原先设的c=0,如果c=0,会出现一些问题,需要特判,
如果c=1,会很有逻辑性,反正现在的这个代码有许多地方我都不能正确的进行思考
思维逻辑不能连贯,缜密,在谁和谁比较,什么情况下c++上几乎没有思考,还是
思维逻辑的问题!!!
方法一: 贪心处理,对左端点进行排序
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
struct P{
int l,r;
bool operator<(const P&T){
return r<T.r;
}
}t[N];
int n;
int select(){
sort(t,t+n);
//对第二个元素进行升序
int q=t[n-1].l;
/*
1 2 _____
2 4 __________
3 4 ______
4 5 ______*
*/
int c=1;
vector<pii> y;
for(int i=1;i<n;i++){
if(t[i].first<=d){
d=max(d,t[i].second);
}
else{
c++;
y.push_back({q,d});
d=t[i].second;
q=t[i].first;
}
}
if(d==t[0].second){ //如果只有一个区间
y.push_back({q,d});
} //这部分内容是将合并后区间的值赋给y数组,输出
if(d!=t[0].second){
y.push_back({q,d}); //最后一个区间
}
for(auto seg:y){
cout<<seg.first<<' '<<seg.second<<endl;
}
return c;
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>t[i].l>>t[i].r;
}
cout<<select();
return 0;
}
方法二: 贪心处理,对右端点进行排序
#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e5+10;
pair<int,int>t[N];
int n;
int select(){
sort(t,t+n);//对第一个元素进行升序排序
int q=t[0].first;
int d=t[0].second;
int c=1;
//假设t[0]为一个独立不能合并的区间
for(int i=1;i<n;i++){
if(t[i].first<=d){
d=max(d,t[i].second);
}
else{
c++;
//没有区间进行合并第二个区间开始做一个不能进行合并的独立区间
d=t[i].second;
}
}
return c;
}
int main(){
cin>>n;
for(int i=0;i<n;i++){
cin>>t[i].first>>t[i].second;
}
cout<<select();
return 0;
}
方法三: y总的合并区间模板
#include<iostream>
#include<algorithm>
#include<vector>
using namespace std;
const int N=1e5+10;
int n;
typedef pair<int ,int>pii;
vector <pii>segs;
void merge(vector<pii>&segs){
vector<pii>res;
sort(segs.begin(),segs.end());
//先将所有区间进行排序
//优先以左端点排序在以右端点进行排序
int st=-2e9,ed=-2e9;
//设置边界
for(auto seg:segs){
if(ed<seg.first){ //如果当前维护区间和枚举区间没有交集
if(st!=-2e9)
res.push_back({st,ed});//如果当前维护的区间不是初始区间
// 将维护的区间存入到res中
st=seg.first; //更新st,ed;
ed=seg.second;
}
else{
// 如果当前维护区间和枚举区间有交集
ed=max(ed,seg.second);
}
}
if(st!=-2e9){ //如果区间不为空,将最后一个区间存入到res中
res.push_back({st,ed});
}
segs=res;
}
int main(){
cin>>n;
int l,r;
for(int i=0;i<n;i++){
cin>>l>>r;
segs.push_back({l,r});
}
merge(segs);
cout<<segs.size();
for(auto t:segs){
//对排序的结果进行输出
//对于vector数组进行这样遍历!!!!!!
cout<<t.first<<' '<<t.second<<endl;
}
return 0;
}
自己的错误代码:
for(int i=1;i<n;){
flag=0;
while(d>=t[i].first&&i<n){
d=max(d,t[i].second);
flag=1;
i++;
}
if(flag==0){
c++;
}
d=t[i].second;
i++;
}
return c;
}