题意:长度为n的序列a,从a中选出两个长度为n/2的子序列b,c.a中每个元素要么属于b要么属于c.
2<=n<=40 -1e9<=a[i]<=1e9 问是否存在子序列b等于子序列c?
初始序列b,c都为空 假如a[1]属于序列b. 那么下一个x=a[1]的数可能属于序列c 中间的数肯定都压入序列b中
若序列b长度大于n/2,无解.
14
1 7 10 1 7 4 5 7 1 10 7 4 5 1
WAWAWA... 按上面算法来执行则无解 实际上有{1,7,10,7,4,5,1}第5个7选给了序列b.
暴力来匹配. TLE... 加个剪纸过了. 这题数据水.可以构造数据来卡主.
折半枚举 前半段和后半段分别选出 A,B,C,D
若B为A的前缀,则把A剩下部分压入字典树.
2<=n<=40 -1e9<=a[i]<=1e9 问是否存在子序列b等于子序列c?
初始序列b,c都为空 假如a[1]属于序列b. 那么下一个x=a[1]的数可能属于序列c 中间的数肯定都压入序列b中
若序列b长度大于n/2,无解.
14
1 7 10 1 7 4 5 7 1 10 7 4 5 1
WAWAWA... 按上面算法来执行则无解 实际上有{1,7,10,7,4,5,1}第5个7选给了序列b.
暴力来匹配. TLE... 加个剪纸过了. 这题数据水.可以构造数据来卡主.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e4+5;
int T,n,a[N],b[N],c[N];
bool flag;
void dfs(int x,int now,int pb,int pc)
{
if(pb>n/2||flag)
return;
if(x==n+1)
{
if(pc==n/2)
flag=true;
return;
}
if(a[x]==b[now]&&pc<pb)
dfs(x+1,now+1,pb,pc+1);
b[++pb]=a[x];
dfs(x+1,now,pb,pc);
}
int main()
{
int T;
cin>>T;
while(T--)
{
flag=false;
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
b[1]=a[1];
dfs(2,1,1,0);
puts(flag?"Good job!!":"What a pity!");
}
return 0;
}
折半枚举 前半段和后半段分别选出 A,B,C,D
若B为A的前缀,则把A剩下部分压入字典树.
若D为C的后缀,则把查询C是否能在字典树上匹配 若能,则得到一解:A+D=B+C.
写的半天 然后还TLE了。。。
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=40;
int T,n,a[N],id[N],b[N],c[N];
int ch[N*20][20],sz;
bool num[N*20];
map<int,int> mp;
void init()
{
memset(ch[0],0,sizeof(ch[0]));
memset(num,0,sizeof(num));
sz=1;
mp.clear();
}
void insert(string s)
{
int u=0;
for(int i=0;s[i];i++)
{
int c=s[i]-'a';
if(!ch[u][c])
{
memset(ch[sz],0,sizeof(ch[sz]));
ch[u][c]=sz++;
}
u=ch[u][c];
}
num[u]=1;
}
int find(string s)
{
int u=0;
for(int i=0;s[i];i++)
{
int c=s[i]-'a';
if(!ch[u][c])
return 0;
u=ch[u][c];
}
return num[u]==1;
}
int main()
{
int T;
cin>>T;
while(T--)
{
int num=0;
init();
bool flag=false;
scanf("%d",&n);
for(int i=0;i<n;i++)
{
scanf("%d",&a[i]);
if(!mp[a[i]])
mp[a[i]]=num+1,id[i]=num++;
else
id[i]=mp[a[i]]-1;
}
if(num>n/2)
{
printf("%s\n","What a pity!");
continue;
}
for(int i=0;i<(1<<(n/2));i++)
{
int pb=0,pc=0;
for(int j=0;j<n/2;j++)
{
if((i>>j)&1)
b[pb++]=id[j];
else
c[pc++]=id[j];
}
if(pb<pc)
swap(b,c),swap(pb,pc);
int j;
for(j=0;j<pc;j++)
if(b[j]!=c[j])
break;
if(j==pc)
{
string s="";
for(;j<pb;j++)
s+='a'+b[j];
insert(s);
}
}
for(int i=0;i<(1<<(n/2))&&flag==false;i++)
{
int pb=0,pc=0;
for(int j=0;j<n/2;j++)
{
if((i>>j)&1)
b[pb++]=id[n/2+j];
else
c[pc++]=id[n/2+j];
}
if(pb<pc)
swap(b,c),swap(pb,pc);
int j,k=pb-pc;
for(j=0;j<pc;j++,k++)
if(b[k]!=c[j])
break;
if(j==pc)
{
string s="";
for(j=0;j<pb-pc;j++)
s+='a'+b[j];
if(find(s))
flag=true;
}
}
if(flag)
printf("%s\n","Good job!!");
else
printf("%s\n","What a pity!");
}
return 0;
}