CF1684C Column Swapping-思维

Column Swapping - 洛谷

本题的线性推理方法还是很难构造的,不可能一眼看出,需要大量的分情况讨论。

对于每一行,设置,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;
}

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qinsanma and Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值