您的位置:首页 > 其它

[HDU] 4513 吉哥系列故事——完美队形II

2013-08-01 15:02 411 查看
题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=4513

方法:模拟,定义数组counts[i]记录当第i个元素必须以一个序列最后一个元素的身份选择出来,该序列的长度是多大,使用countsEqual[i]表示第i元素直接前面包括自己有多少个连续的数字的值等于它自己。

如对于数据:

  index: 1 2 3 4 5 6 7 8 9 10 11 12  

  value:   1 11 12 21 25 25 25 25 21 12 12 12

counts[i]:  1 1 1 1 1 2 3 4 6 8 2 3

countsEqual[i]:1 1 1 1 1 2 3 4 1 1 2 3

在严格上升的区间里(第一个数默认为一个严格的上升区间,程序中是通过在数组的第一个数前面在加一个负数来实现), 每一个 counts[i]和countsEqual[i]都等于1,自成一个序列.

在严格的下降区间里,每一个counts[i]都为1,而countsEqual[i]要分情况讨论,首先获取其前一个数字,下标为i-1(这里的i一定大于等于2,因为第一个数假定是在一个严格的上升区间内),获取的 counts[i-1],若i-1-counts[i-1]个元素存在且等于第i元素,则counts[i] = counts[i-1]+2,标识合法序列得到扩展;如上述数据,当扫描到第10个数12时,

nums[10-1-counts[10-1]] == nums[10] == 12,则nums[10] =nums[10-1]+2=8;

否则,counts[i]和countsEqual[i]都等于1,自成一个序列。

在严格的相等区间里,分情况讨论,若在进入该区间前是一个严格上升区间,则说明该区间其实是在非降区间中,每一个 counts[i]和countsEqual[i]都等于第i个数在该区间中已经连续的个数,如上述第6个元素,其在严格的相等区间出现时,已经连续了2个。

若在进入该区间前是一个严格下降区间,则说明该区间其实是在非升区间中,counts[i]同上处理,而countsEqual[i]要分情况讨论,同样首先获取其前一个数字,下标为i-1(这里的i一定大于等于2,因为第一个数假定是在一个严格的上升区间内),获取的 counts[i-1],若i-1-counts[i-1]个元素存在且等于第i元素,则counts[i] = counts[i-1]+2,合法序列得到扩展;否则counts[i]就等于countsEqual[i],如上述到第11个数。

代码:

#include <iostream>
#include <queue>
#include <map>
#include<algorithm>
using namespace std;
int nums[100001];
int n;
int countsEqual[100001];
int counts[100001];
int main()
{
int tc = 0;
scanf("%d",&tc);
while(tc>0)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&nums[i]);
int max=0;
int j = 1;
int last=nums[0]=-1;
bool increase=true;
memset(countsEqual,0,sizeof(countsEqual));
memset(counts,0,sizeof(counts));
while(j <=n)
{
if(nums[j]>last)
{
while(nums[j]>last && j<=n)
{
increase=true;
countsEqual[j]=1;
counts[j]=1;
max = max > 1 ? max :1;
last = nums[j];
j++;
}
}
else if(nums[j]==last)
{
while(nums[j]==last && j<=n )
{
countsEqual[j]= j>=2 ? (countsEqual[j-1]+1):1;
if(increase)
{
counts[j] = countsEqual[j];
max = max > counts[j] ? max :counts[j];
}
else
{
int t =counts[j-1];
if(j-1-t >0 && nums[j-1-t]==nums[j])
{
max = max >(t+2) ? max : (t+2);
counts[j]=t+2;
}
else
{
max = max > countsEqual[j] ? max :countsEqual[j];
counts[j] = countsEqual[j];
}
}
last = nums[j];
j++;
}
}
else if(nums[j]<last)
{
while(nums[j]<last && j<=n )
{
increase=false;
countsEqual[j] = 1;
int t =counts[j-1];
if(j-1-t >0 && nums[j-1-t]==nums[j])
{
max = max >(t+2) ? max : (t+2);
counts[j] = t+2;
}
else
{
max = max > 1 ? max :1;
counts[j]=1;
}
last = nums[j];
j++;
}
}
}
for(int i=1;i<=n;i++)
max = max > counts[i] ? max :counts[i];
cout<<max<<endl;
tc--;
}
return 0;
}


感想 :好好模拟,要思路清晰
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: