zoukankan      html  css  js  c++  java
  • E. The Contest 解析(思維、前綴和)

    Codeforce 1257 E. The Contest 解析(思維、前綴和)

    今天我們來看看CF1257E
    題目連結

    題目
    有三個籃子,放數字(1sim n)。求最小的數字移動次數,使得三個籃子裡的數字由小排到大。

    前言

    很久沒有寫題目了,主要是自己本科也不是做電腦的,而且寫難度2000的題目真的遇到很多挫折...,常常寫到想放棄。
    這題也搞了很久,看了別人的解析才知道怎麼做,腦袋打結了一整天。

    想法

    這題其實有dp解法,但是這篇文章就不講了。
    第一眼看到這題目,可能會覺得就是要找到一組數字([l,r])表示第一個籃子放([1,l]),第二個籃子放([l+1,r-1]),第三個籃子放([r,n])。但是(nle2e5),所以我們應該是遍歷(l)(1sim n),然後快速地找出哪個(r)最好。
    (cnt[i][j])表示第(i)個籃子擁有幾個([1,j])的數字。
    假設目前決定好了([l,r]),那麼需要的步數即:(cnt[1][l+1sim n]+cnt[2][1sim l]+cnt[2][rsim n]+cnt[3][1sim r-1])
    也就是我們計算要幾步才能把原本不在正確的籃子裡的數字放到正確的籃子裡。
    假設已經固定了(l)(cnt[1][l+1sim n]+cnt[2][1sim l])就可以用前綴和輕鬆算出來,接著我們只要決定(cnt[2][rsim n]+cnt[3][1sim r-1])到底是哪個(r)才會最小就好。
    而只要事先計算對於每個後綴([rsim n]),最小的(cnt[2][rsim n]+cnt[3][1sim r-1])是多少,就可以解決這題了。

    程式碼:

    const int _n=2e5+10;
    int t,n,m,k[3],pos[_n],cnt[3][_n],mn[_n],ans=0x7f7f7f7f;
    main(void) {ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
      rep(_,0,3){cin>>k[_];n+=k[_];}
      rep(_,0,3)rep(i,0,k[_]){cin>>t;pos[t]=_;}
      rep(i,1,n+1)rep(_,0,3)cnt[_][i]=cnt[_][i-1]+(pos[i]==_);
      mn[n+1]=cnt[2][n];
      per(i,1,n+1)mn[i]=min(mn[i+1],cnt[1][n]-cnt[1][i-1]+cnt[2][i-1]);
      rep(i,0,n+1)ans=min(ans,cnt[0][n]-cnt[0][i]+cnt[1][i]+mn[i+1]);
      cout<<ans;
      return 0;
    }
    

    標頭、模板請點Submission看
    Submission

  • 相关阅读:
    cmd输入输出重定向
    【转载】标准输入输出、错误输出、重定向标准输出
    cmd 重定向
    Windows下cmd标准输入输出重定向
    Windows 命令行输入输出重定向问题
    MATLAB数值计算与符号运算
    选择排序法 冒泡排序法 本质上是对内存进行整理
    学习笔记:Monkey runner(一)
    Monkey test
    fiddler:快速标识接口
  • 原文地址:https://www.cnblogs.com/petjelinux/p/14421279.html
Copyright © 2011-2022 走看看