HDU6049-Sdjpx Is Happy

Sdjpx Is Happy

                                                                   Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)
                                                                                             Total Submission(s): 528    Accepted Submission(s): 221


Problem Description
Sdjpx is a powful man,he controls a big country.There are n soldiers numbered 1~n(1<=n<=3000).But there is a big problem for him.He wants soldiers sorted in increasing order.He find a way to sort,but there three rules to obey.
1.He can divides soldiers into K disjoint non-empty subarrays.
2.He can sort a subarray many times untill a subarray is sorted in increasing order.
3.He can choose just two subarrays and change thier positions between themselves.
Consider A = [1 5 4 3 2] and P = 2. A possible soldiers into K = 4 disjoint subarrays is:A1 = [1],A2 = [5],A3 = [4],A4 = [3 2],After Sorting Each Subarray:A1 = [1],A2 = [5],A3 = [4],A4 = [2 3],After swapping A4 and A2:A1 = [1],A2 = [2 3],A3 = [4],A4 = [5].
But he wants to know for a fixed permutation ,what is the the maximum number of K?
Notice: every soldier has a distinct number from 1~n.There are no more than 10 cases in the input.
 

Input
First line is the number of cases.
For every case:
Next line is n.
Next line is the number for the n soildiers.
 

Output
the maximum number of K.
Every case a line.
 

Sample Input
  
  
2 5 1 5 4 3 2 5 4 5 1 2 3
 

Sample Output
  
  
4 2
Hint
Test1: Same as walk through in the statement. Test2: [4 5] [1 2 3] Swap the 2 blocks: [1 2 3] [4 5].
 

Source
 

题意:给一个序列,问最多能分成多少组,组内排序后,可以交换两个组的顺序,使整个序列升序

解题思路:先预处理,mi[i][j]记录区间最小值,ma[i][j]记录区间最大值,dp[i][j]记录(i,j)段最多可以被分成几个小段, x[i]记录从i开始的上次的可行区间的右端点。然后设要交换的区间为a,b。先枚举a的左右端点并且a必须满足可行,即dp[i][j]!=0,同时必须满足,a为最左边的段或者a左边的段包括了(1,i-1)的数字。设p为a中的最大值,则如果k==n的话,那么b是最右边的段,否则b右边的段为(k+1,n),且必须包括(k+1,n)中的所有数,然后枚举b的左端点k使b合法并且mi[t][k]==i,才能保证a和b交换后整个数列从1~n递增


#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <vector>
#include <bitset>
#include <functional>

using namespace std;

#define LL long long
const int INF = 0x3f3f3f3f;
const LL mod=1000000007;

int n,a[3009],x[3009];
int dp[3009][3009],ma[3009][3009],mi[3009][3009];

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i=1; i<=n; i++) scanf("%d",&a[i]),dp[i][i]=1,ma[i][i]=mi[i][i]=a[i],x[i]=i;
        for(int i=2; i<=n; i++)
            for(int j=1; j+i-1<=n; j++)
            {
                ma[j][i+j-1]=max(ma[j][j+i-2],a[j+i-1]);
                mi[j][i+j-1]=min(mi[j][i+j-2],a[i+j-1]);
            }
        for(int i=2; i<=n; i++)
        {
            for(int j=1; j+i-1<=n; j++)
            {
                int k=i+j-1;
                if(ma[j][k]-mi[j][k]+1!=i) dp[j][k]=0;
                else
                {
                    if(mi[j][k]<mi[j][x[j]]) dp[j][k]=1;
                    else dp[j][k]=dp[j][x[j]]+dp[x[j]+1][k];
                    x[j]=k;
                }
            }
        }
        int ans=dp[1][n];
        for(int i=1; i<=n; i++)
        {
            for(int j=i; j<=n; j++)
            {
                if(dp[i][j]&&(i==1||(dp[1][i-1]&&mi[1][i-1]==1)))
                {
                    int p=ma[i][j];
                    if(p==n||(dp[p+1][n]&&ma[p+1][n]==n))
                    {
                        for(int k=j+1; k<=p; k++)
                            if(dp[k][p]&&mi[k][p]==i)
                                ans=max(ans,dp[1][i-1]+1+dp[j+1][k-1]+1+dp[p+1][n]);
                    }
                }
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值