题意:
分析:
DP
来贡献一发最劣解的做法
- 暴力
我们发现由于长度之和不超过(2^{13}) ,所以放进去的块可以用一个不超过 (2^{14}) 的数字状压出来,其次我们手玩样例会发现一个性质,就是过程中拼出来的序列满足大小形状类倒着的 V
证明:
若存在 (a>b<c) ,那么 (b) 没有办法和任何一个块消掉
所以我们把序列拆成左右两个单调的序列,然后每次判断一下能不能并到左边或者右边,只要满足以下任何一个条件即可:
- 左序列或者右序列为空
- 小于左序列或者右序列的最小值
然后我们就得到了一个 (O(tn2^{26} imes13)) 的做法
- 优化
我们发现左右序列的和值固定,所以只需要枚举左序列的状态就可以了,复杂度降低为 (O(tn2^{13} imes 13)) ,但是由于直接枚举是跑满的,所以会 TLE 的
- 正解
我们发现状态转移是固定的,所以不需要枚举状态,直接 DFS 就可以了,并且预处理一下 highbit ,复杂度就变成了常数极小的 (O(n2^{13}))
tip:
-
可能存在一种情况就是,左右序列都单调递增,所以转移的时候每次记得把左右序列相连的部分能合并就合并,不然会像我一样直接白给好多发
比如 2|2 的情况添加一个 4,原本是添加不进去的,但先合并之后变成 4|0,然后就可以添加进去了
-
记忆化一下,保证复杂度正确
代码:
#include<bits/stdc++.h>
#define inl inline
#define reg register
#define mk(x,y) make_pair(x,y)
#define fir first
#define sec second
using namespace std;
namespace zzc
{
typedef long long ll;
inl ll read()
{
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;
}
const ll maxn = 1005;
const ll maxm = (1<<14);
ll n,t;
bool vis[maxn][maxm],ans[maxn];
ll sum[maxn],a[maxn],hig[maxm];
inl ll merge(ll x,ll y,ll k)//表示将 k 加到 x 序列上
{
if(hig[x]>hig[y])//先将x序列最大值并到y序列上, 参考 tip:1
{
ll tmp=hig[x];
x-=tmp;
y+=tmp;
}
if(x&&(x&(-x))<k) return -1;x+=k;
if(hig[x]==hig[y])//合并两个序列相连的部分
{
ll tmp=hig[x];
x+=tmp;
y-=tmp;
}
return x;
}
bool dfs(ll pos,ll lef)
{
ll rig,now;
rig=sum[pos]-lef;
if(pos==n)
{
//将左右序列合并化到最简
lef=merge(lef,rig,0);
rig=sum[pos]-lef;
if(lef==sum[n]&&(lef&(lef&(-lef)))==lef) return true;
if(rig==sum[n]&&(rig&(rig&(-rig)))==rig) return true;
return false;
}
if(vis[pos][lef]) return false;
vis[pos][lef]=true;
now=merge(lef,rig,a[pos+1]);
if(now!=-1&&dfs(pos+1,now))
{
ans[pos+1]=true;
return true;
}
now=merge(rig,lef,a[pos+1]);
if(now!=-1&&dfs(pos+1,sum[pos+1]-now))
{
ans[pos+1]=false;
return true;
}
return false;
}
void init()
{
for(reg ll i=1;i<(1<<14);i++)// 预处理 highbit
{
if((i&(-i))==i) hig[i]=i;
else hig[i]=hig[i-1];
}
}
void work()
{
init();
t=read();
while(t--)
{
memset(vis,false,sizeof(vis));
memset(ans,false,sizeof(ans));
n=read();
for(reg ll i=1;i<=n;i++) a[i]=read(),sum[i]=sum[i-1]+a[i];
if(!dfs(0,0)) printf("no");
else for(reg ll i=1;i<=n;i++) printf("%c",(ans[i]?'l':'r'));
puts("");
}
}
}
int main()
{
zzc::work();
return 0;
}