bzoj4576【Usaco2016 Open】262144
4576: [Usaco2016 Open]262144
Time Limit: 10 Sec
Memory Limit: 128 MB
Submit: 97
Solved: 73
[ Submit][ Status][ Discuss]
Description
Bessie likes downloading games to play on her cell phone, even though she does find the small touch
screen rather cumbersome to use with her large hooves.
She is particularly intrigued by the current game she is playing. The game starts with a sequence of
N positive integers (2≤N≤262,144), each in the range 1…40. In one move, Bessie can take two adja
cent numbers with equal values and replace them a single number of value one greater (e.g., she migh
t replace two adjacent 7s with an 8). The goal is to maximize the value of the largest number presen
t in the sequence at the end of the game. Please help Bessie score as highly as possible!
Input
The first line of input contains N, and the next N lines give the sequence of N numbers at the start
of the game.
Output
Please output the largest integer Bessie can generate.
Sample Input
4 1 1 1 2
Sample Output
3 In this example shown here, Bessie first merges the second and third 1s to obtain the sequence 1 2 2 , and then she merges the 2s into a 3. Note that it is not optimal to join the first two 1s.
HINT
Source
Platinum
메서드1: DP
f[i][j]는 j를 왼쪽 단점으로 하는 서열을 i의 오른쪽 단점 오른쪽에 있는 한 점의 위치로 합성하는 것을 의미한다. 즉, 구간 [j, x]이 i를 합성할 수 있다면 f[i][j]=x+1이다.
DP 전환 방정식은 f[i][j]=f[i-1][f[i-1][j]]입니다.
그리고 f[i][j]>0을 만족시키는 i에 대해 최대치, 즉 답을 얻는다.
시간 복잡도 O (n*logn).
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define N 270000
using namespace std;
int n,ans;
int f[60][N];
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
int main()
{
n=read();
F(i,1,n){int x=read();f[x][i]=i+1;}
F(i,2,58) F(j,1,n)
{
if (!f[i][j]) f[i][j]=f[i-1][f[i-1][j]];
if (f[i][j]) ans=i;
}
printf("%d
",ans);
return 0;
}
방법2: 단조 창고
만약 서열의 값을 높이로 상상한다면, 합병의 순서는 반드시 '계곡' (양쪽보다 낮은 점) 에서 시작될 것이다.
그리고 단조로운 창고로 유지하고 계곡을 만날 때마다 답을 계산한다.
또 하나의 세부 사항은 어떤 상황에서 창고를 비워야 하는지 주의해야 한다. (코드 참조)
시간 복잡도 O (n).
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<algorithm>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define N 270000
using namespace std;
int n,ans,cnt,top,lg[N];
struct data{int val,tot;}s[N],a[N];
inline int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void clear()
{
for(;top>1;top--) s[top-1].tot+=s[top].tot/(1<<(s[top-1].val-s[top].val));
ans=max(ans,s[top].val+lg[s[top].tot]);
top=0;
}
void combine(int val)
{
for(;top>1;top--)
{
if (s[top-1].val>val) return;
int num=1<<(s[top-1].val-s[top].val);
if (s[top].tot%num==0) s[top-1].tot+=s[top].tot/num;
else
{
data tmp=s[top];
clear();s[++top]=tmp;
return;
}
}
}
int main()
{
n=read();
for(int i=2;i<=n;i<<=1) lg[i]=1;
F(i,1,n) lg[i]+=lg[i-1];
F(i,1,n)
{
int x=read();
if (x==a[cnt].val) a[cnt].tot++;
else a[++cnt]=(data){x,1};
}
F(i,1,cnt)
{
if (!top||a[i].val<s[top].val){s[++top]=a[i];continue;}
combine(a[i].val);
int num=1<<(a[i].val-s[top].val);
if (s[top].tot%num==0)
{
a[i].tot+=s[top].tot/num;
s[top]=a[i];
}
else
{
a[i].tot+=s[top].tot/num;
clear();s[++top]=a[i];
}
}
clear();
printf("%d
",ans);
return 0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
bzoj4576【Usaco2016 Open】262144Time Limit: 10 Sec Memory Limit: 128 MB Submit: 97 [ Submit][ Status][ Discuss] She is particularly intrigued by the cur...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.