要找出所有极长(尽可能长)的不严格上升段,并找到段中右端点权值-左端点权值最大的那些段,输出左右端点
也就是说
- 首先是右端点权值-左端点权值尽可能大
- 对于ai~ak都相等时,尽可能选择从ai开始,因为此时极长
- 每个点只能出现在一个区间内
思路:
遍历一遍区间,用于要找出所有的极大上升段,所以一个段要尽可能地长,只要一个段是上升的,就继续遍历,直到不能上升为止,然后压入目前的段,并计算他的右端点权值-左端点权值
有点像倍增找区间的办法,不过本题不能用倍增
注意!
找到答案后的排序,由于左右区间要升序,所以排序应该是双关键字的
bool cmp(node a,node b)
{
if(a.data!=b.data)
return a.data>b.data;
else
return a.l<b.l;
}
#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;
struct node
{
int l,r;
int data;
};
int a[100010];
bool cmp(node a,node b)
{
if(a.data!=b.data)
return a.data>b.data;
else
return a.l<b.l;
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
cin>>a[i];
//找到所有极大的连续不严格上升区间
int l=1;
vector<node> q;
for(int i=2;i<=n;i++)
{ //此时应该断开
if(a[i]<a[i-1])
{
q.push_back({l,i-1,a[i-1]-a[l]});
l=i; //区间断开,l变为i
}
}
q.push_back({l,n,a[n]-a[l]});
sort(q.begin(),q.end(),cmp);
for(int i=0;i<(int)q.size();i++)
{ //只需要输出最大权值差的区间
if(q[i].data==q[0].data)
cout<<q[i].l<<' '<<q[i].r<<' ';
}
//记得换行
cout<<'\n';
}
}