题解 P9746 「KDOI-06-S」合并序列
考虑区间 DP。设
这样是 不一定不能过。 考虑优化:设
这样是 有很大概率能过。 考虑优化:设
其实
整个转移过程是
总时间复杂度
#include<bits/stdc++.h>
#define For(i,a,b) for(int i=(a);i<=(b);++i)
#define Rof(i,a,b) for(int i=(a);i>=(b);--i)
using namespace std;
const int Maxn=511;
inline int read()
{
char ch=getchar();
int f=1,x=0;
while(ch>'9' || ch<'0')
{
if(ch=='-') f=-1;
ch=getchar();
}
while(ch>='0' && ch<='9')
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int T,n,a[Maxn+5],s[Maxn+5];
int f[Maxn+5][Maxn+5],g[Maxn+5][Maxn+5],h[Maxn+5][Maxn+5];
int fk[Maxn+5][Maxn+5],gk[Maxn+5][Maxn+5],hk[Maxn+5][Maxn+5];
vector<array<int,3>> ans;
inline void Solve(int l,int r,int id)
{
if(l==r) return;
int d=fk[l][r],a=hk[l][s[r]^s[d-1]];
int w=s[r]^s[d-1]^s[a]^s[l-1],b=gk[a+1][w],c=g[a+1][w];
if(l==0) exit(0);
Solve(d,r,id+(d-l)),Solve(b,c,id+(b-l)),Solve(l,a,id);
ans.push_back({id,id+(b-l)-(a-l),id+(d-l)-(a-l)-(c-b)});
}
inline void Solve()
{
n=read(); For(i,1,n) a[i]=read(),s[i]=s[i-1]^a[i];
memset(f,0,sizeof(f));
For(i,1,n+1) For(j,0,Maxn) g[i][j]=h[i][j]=n+1;
Rof(l,n,1)
{
memcpy(g[l],g[l+1],sizeof(g[l+1]));
memcpy(gk[l],gk[l+1],sizeof(gk[l+1]));
f[l][l]=1,g[l][a[l]]=l,gk[l][a[l]]=l;
For(i,0,Maxn) if(g[l+1][i]<h[l][a[l]^i])
h[l][a[l]^i]=g[l+1][i],hk[l][a[l]^i]=l;
For(r,l+1,n)
{
For(k,l+1,r) if(f[k][r] && h[l][s[r]^s[k-1]]<k) {f[l][r]=1,fk[l][r]=k; break;}
if(f[l][r])
{
int w=s[r]^s[l-1]; if(g[l][w]>r) g[l][w]=r,gk[l][w]=l;
For(i,0,Maxn) if(g[r+1][i]<h[l][w^i])
h[l][w^i]=g[r+1][i],hk[l][w^i]=r;
}
}
}
if(!f[1][n]) {printf("Shuiniao\n"); return;}
printf("Huoyu\n"),Solve(1,n,1);
cout<<ans.size()<<endl;
for(auto i:ans) printf("%d %d %d\n",i[0],i[1],i[2]);
ans.clear();
}
int main()
{
T=read();
while(T--) Solve();
return 0;
}