Advertisement
Mysakure

19湖南G

Oct 1st, 2019
143
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 3.60 KB | None | 0 0
  1. /*解题思路:
  2. 我们容易想到一个n^3的贪心:每次找到最小的可以放进来的第j列,同时记录当前连续的依然相等的行。第j列可以放进来的条件为:对于当前每一个依然相等的连续行(i,i+1)(i,i+1)(i,i+1),有C[i][j]&lt;=C[i+1][j]C[i][j] &lt;= C[i+1][j]C[i][j]<=C[i+1][j]。
  3. 一共要找m次列,每次找列是枚举m个列,而检查列是否符合条件需要检查当前所有依然相等的连续行,最差情况下要检查n次。总的复杂度O(m2n)O(m^2n)O(m
  4. 2
  5.  n),肯定是不行的。考虑优化其中的一个步骤。
  6. 想到优化检查这一步,不是暴力检查,而是用cnt[j]cnt[j]cnt[j]记录第jjj列有多少行满足(C[i][j]>C[i+1][j])(C[i][j] &gt; C[i+1][j])(C[i][j]>C[i+1][j])。如果为0,则表示这一列可以加入。这样把检查优化到了O(1),但是每一次加入一列之后要去更新其他没加入的列的cntcntcnt。
  7. 什么情况下一列的cnt会减少?也就是什么情况下对于还没放入的第j列,(C[i][j]>C[i+1][j])(C[i][j] &gt; C[i+1][j])(C[i][j]>C[i+1][j])的影响被消除?
  8. 只要前面放入的列中,有一列k满足(C[i][k]&lt;C[i+1][k])(C[i][k]&lt;C[i+1][k])(C[i][k]<C[i+1][k]),那么(C[i][j]>C[i+1][j])(C[i][j] &gt; C[i+1][j])(C[i][j]>C[i+1][j])对于第j列的影响就被消除了。
  9. 记录当前依然相等的连续行,加入新的一列j时,如果第j列可以把某连续行(i,i+1)分开(也就是C[i][j]<C[i+1][j]),那么就更新剩余列的cnt。因为只更新连续行,最多更新n次(一共就n行,每更新一次最少会少1个连续行),更新一次的复杂度是O(m)。
  10. 总的复杂度为O(m2+nm)O(m^2+nm)O(m
  11. 2
  12.  +nm)
  13.  
  14. 代码:
  15. ————————————————
  16. 版权声明:本文为CSDN博主「_ 泛白」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
  17. 原文链接:https://blog.csdn.net/qq_43202683/article/details/100170570
  18. */
  19. #include<bits/stdc++.h>
  20. #define ll long long
  21. using namespace std;
  22. const int maxn = 2e3 + 50;
  23. int n, m;
  24. int c[maxn][maxn];
  25. int cnt[maxn];// 有多少个不符合条件的
  26. int dif[maxn];//dif[i]=1 表示第i行和i+1行已经不相等了
  27. int vis[maxn];
  28. void init(){
  29.     memset(cnt, 0, (m+1)<<2);
  30.     memset(vis, 0, (m+1)<<2);
  31.     memset(dif, 0, (n+1)<<2);
  32.     for(int i = 1; i <= n; ++i){
  33.         for(int j = 1; j <= m ;++j){
  34.             scanf("%d", &c[i][j]);
  35.             if(i!=1){
  36.                 cnt[j] += (c[i-1][j] > c[i][j]);
  37.             }
  38.         }
  39.     }
  40. }
  41. vector<int> ans;
  42. void sol(){
  43.     ans.clear();
  44.     while(ans.size() < m){
  45.         int j;
  46.         for(j = 1; j <= m; ++j){
  47.             if(vis[j] || cnt[j] > 0) continue;
  48.             break;
  49.         }
  50.         if(j > m){//没找到
  51.             printf("-1\n"); return;
  52.         }
  53.         ans.push_back(j);
  54.         vis[j] = 1;
  55.         for(int i = 1; i < n; ++i){
  56.             if(dif[i]) continue;
  57.             if(c[i][j] >= c[i+1][j]) continue;
  58.             dif[i] = 1;
  59.             for(int k = 1; k <= m; ++k){
  60.                 if(c[i][k] > c[i+1][k]) cnt[k]--;
  61.             }
  62.         }
  63.     }
  64.     for(int i = 0; i < ans.size(); ++i){
  65.         if(i > 0) printf(" ");
  66.         printf("%d", ans[i]);
  67.     }printf("\n");
  68. }
  69. int main()
  70. {
  71.     while(scanf("%d%d", &n, &m)!=EOF){
  72.         init();sol();
  73.     }
  74. }
  75.  
  76. ————————————————
  77. 版权声明:本文为CSDN博主「_ 泛白」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
  78. 原文链接:https://blog.csdn.net/qq_43202683/article/details/100170570
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement