本题的线性推理方法还是很难构造的,不可能一眼看出,需要大量的分情况讨论。
对于每一行,设置,x,y,l。 分别是代表第一个交换的列,第二个交换的列,当前最近的满足不下降的位置
比如 1 2 3 4当我们遇到4的时候,l=3;
然后,一旦我们当前遍历的小于l代表的值,例如
1 2 4 3 ,遍历到3,当前l=3位置上a[i]是4,那么会不满足,必须产生交换,此时,我们交换方案是x=3,y=4 ,指位置
此时我们继续遍历
遇到下降序列时
1 2 4 3 2 显然我们把y修改成 5会更优
遇到下降序列再次遇到下降序列时
1 2 4 3 2 1显然这个序列已经无法满足交换一次了,因为我们交换一次仅仅能挽留三个(4 3 2)或者两个(4 3),而此时有四个,无法挽留,我们继续修改y即可。
遇到下降序列遇到上升情况时
1 2 4 3 2 3 ,显然不满足,我们修改y不会影响最后结果
1 2 4 3 2 4 (5),此时不能再修改y
所以我们可以得出结论,当当前遍历位置是比l位置要小的时候,尽管遍历即可,一定会最优,要不然就是无法挽回的
当我们遇到上升序列时
1 2 4 3 4(5)可以看出,此时 4 与3已经是必须交换不可了,如果今后再次出现下降序列,比如最后一个4或者5后面出现3 ,那就无法挽回了。
#include <bits/stdc++.h>
# define mod 100000000
using namespace std;
typedef long long int ll;
vector<int>v[200000+10];
int main()
{
int t;
cin>>t;
while(t--)
{
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++)
{
v[i].clear();
}
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
int x;
cin>>x;
v[i].push_back(x);
}
}
int x=0,y=0;
int l=0;
for(int i=1;i<=n;i++)
{
l=0;
for(int j=1;j<m;j++)
{
if(v[i][j]<v[i][l])
{
if(!x)
x=l;
y=j;
}
if(v[i][j]>v[i][j-1])
l=j;
}
}
if(x==y&&y==0)
{
cout<<1<<" "<<1<<endl;
continue;
}
else
{
for(int i=1;i<=n;i++)
{
swap(v[i][x],v[i][y]);
}
int flag=0;
for(int i=1;i<=n;i++)
{
for(int j=1;j<m;j++)
{
if(v[i][j]<v[i][j-1])
{
cout<<-1<<endl;
flag=1;
break;
}
}
if(flag)
{
break;
}
}
if(!flag)
{
cout<<x+1<<" "<<y+1<<endl;
}
}
}
return 0;
}