您的位置:首页 > 移动开发

HDU6049-Sdjpx Is Happy

2017-08-03 21:35 225 查看


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

2017 Multi-University Training Contest - Team 2

 

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

解题思路:先预处理,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]
;
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]
&&ma[p+1]
==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]
);
}
}
}
}
printf("%d\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: