这题测得我心累…
写了个spj拿着n组数据一组一组手测
其实我都不知道我这样做是不是对的..反正A了不管了…
我们枚举第一个人选哪个,然后f[i][j][k]表示处理完前i个,第i个人选的情况是j(0代表左边,1代表右边),为了使第i个人合法,第i+1个人应该选k(0代表必须左,1代表必须右,2代表两个都行)这种情况是否可行
用一个pre记录转移,dp完前n-1个后,对于一个合法的f[n-1][j][k],我们恢复每个人选的情况,看第n个人可以选哪个,选完再判一下第一个人是否合法
…..
感觉好像有哪里不太对劲…不管了反正A了….
code:
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<cmath>
#include<ctime>
#include<bitset>
#include<string>
#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<climits>
#include<complex>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
const int maxn = 1000005;
int n;
ll a[maxn];
// 1 i i+1
bool f[maxn][2][3];
int pre[maxn][2][3];
inline int id(const int x,const int y){ return x*10+y; }
int now,ti,i,j;
inline void trans(const int i2,const int j2)
{
if(f[now][i2][j2]) return;
f[now][i2][j2]=true;
pre[now][i2][j2]=id(i,j);
}
int t[maxn];
bool judge()
{
int s1=a[1],s2=a[2];
if(t[n]) s2<<=1;
if(!t[2]) s1<<=1;
if(s1>=s2&&!t[1]) return true;
if(s2>=s1&&t[1]) return true;
return false;
}
int main()
{
scanf("%d",&n);
for(i=1;i<=n;i++) scanf("%d",&a[i]);
for(ti=1;ti>=0;ti--)
{
if(!ti)
{
memset(f,false,sizeof f);
if(a[1]>=a[2]) f[1][0][2]=true;
else if(a[1]*2>=a[2]) f[1][0][0]=true;
}
if(ti)
{
memset(f,false,sizeof f);
if(a[2]>=a[1]*2) f[1][1][2]=true;
else if(a[2]>=a[1]) f[1][1][2]=true;
else if(a[2]*2>=a[1]) f[1][1][1]=true;
}
for(int x=2;x<n;x++)
{
now=x;
for(i=0;i<2;i++) for(j=0;j<3;j++) if(f[now-1][i][j])
{
ll s1=a[x],s2=a[x+1];
if(i) s2<<=1;
if(j!=2)
{
if(!j)
{
if(s1>=s2) trans(0,2);
else if((s1<<1)>=s2) trans(0,0);
}
else
{
if(s2>=(s1<<1)) trans(1,2);
else if(s2>=s1) trans(1,1);
}
}
else
{
if(s1>=s2) trans(0,2);
else if((s1<<1)>=s2) trans(0,0);
if(s2>=(s1<<1)) trans(1,2);
else if(s2>=s1) trans(1,1);
}
}
}
t[1]=-1;
for(i=0;i<2;i++) for(j=0;j<3;j++) if(f[n-1][i][j]&&t[1]==-1)
{
int tti=i,tj=j; now=n-1; t[1]=ti;
while(now!=1)
{
t[now]=tti;
int ttj=pre[now][tti][tj]%10;
tti=pre[now][tti][tj]/10; tj=ttj;
now--;
}
ll s1=a[n],s2=a[1];
if(t[n-1]) s2<<=1;
if(!t[1]) s1<<=1;
if(s1>=s2&&(!j||j==2))
{
t[n]=0;
if(judge()) break;
}
if(s2>=s1&&j)
{
t[n]=1;
if(judge()) break;
}
t[1]=-1;
}
if(t[1]!=-1)
{
for(i=1;i<n;i++) printf("%d ",i+t[i]>n?1:i+t[i]);
printf("%d\n",i+t[i]>n?1:i+t[i]);
break;
}
}
if(t[1]==-1) puts("NIE");
return 0;
}