Codeforces Round #591(Div.2) D. Sequence Sorting(사고+dp)

10555 단어 사유dp

D. Sequence Sorting


제목:


입력은 q(3e5)q(3e5)q(3e5)조 데이터 각 조 데이터 입력 n(∑n≤3e5)n(\sum n\leq3e5)n(∑n≤3e5) 다음 행은 a 1, a 2,..., a n(1≤a i≤n)a1,a_2,\dots,a_n(1\leq a i\leq n)a1, a2,..., an(1≤ai≤n) 한 번의 조작으로 한 숫자를 가장 왼쪽 또는 가장 오른쪽으로 이동할 수 있으며, 최소 몇 번의 조작을 거치면 서열이 내려가지 않는 서열로 변할 수 있는지 묻는다.

문제 풀이:


모든 숫자를 한 번만 이동시켜 숫자를 이산화시키고 서열의 질서성을 관찰하는 것도 괜찮다.사실 하나의 성질을 발견할 수 있다. 연속적으로 질서가 있는 부분의 숫자는 움직이지 않고 다른 숫자는 왼쪽으로 이동하거나 오른쪽으로 이동하기 때문에 연속적으로 질서가 있는 부분의 길이를 최대화하면 된다.

코드:

#include
using namespace std;
const int N=3e5+9;
int q,a[N],n,b[N];
bool vis[N];
int f[N];
vector<int>g[N];
int dp[N];
void solve(){
    //memset(dp,0,sizeof(dp));
    sort(b+1,b+n+1);int nb;
    nb=unique(b+1,b+n+1)-b-1;
   // for(int i=1;i<=nb;i++)cout<
    int ans=1;dp[1]=1;
    for(int i=1;i<nb;i++){
        int x=b[i],y=b[i+1];
        if(g[x].back()<g[y][0])dp[i+1]=dp[i]+1;else dp[i+1]=1;
        ans=max(ans,dp[i+1]);
    }
    cout<<nb-ans<<endl;
}
int main(){
 //   freopen("tt.in","r",stdin),freopen("tt.out","w",stdout);
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    cin>>q;
    while(q--){
        cin>>n;
        for(int i=1;i<=n;i++)cin>>a[i],b[i]=a[i],g[a[i]].push_back(i);
        solve();
        for(int i=1;i<=n;i++)g[a[i]].clear();
    }
    return 0;
}

좋은 웹페이지 즐겨찾기