【问题描述】
有n个人坐成一排,这n个人都在某一个小组中,同一个小组的所有人所坐的位置一定是连续的。
有一个记者在现场进行采访,他每次采访都会询问一个人其所在的小组有多少人,被询问的每个人都给出了正确的答案,但是由于时间仓促,记者不一定询问了每个人,我们记录一个长度为n的答案序列,序列的第i个数表示第i个人的回答,如果为0则表示记者没有询问过这个人。
记者发现,对于一些情况,他可以唯一确定这排所有人的分组,而对于另外一些情况则不能,于是记者开始好奇,对于某一个答案序列,他能不能做到这一点,如果能的话输出1,否则输出0。
【输入格式】
第一行一个正整数T,表示数据组数。
接下来T组数据,每组数据第一行一个正整数n,表示人数,接下来一行n个非负整数表示答案序列,数据保证至少有一种分组方式能生成该答案序列。
【输出格式】
对于每一组测试数据输出一行一个数(0或1),表示答案。
【输入样例】
4
5
0 2 3 0 0
3
0 2 0
6
3 0 0 0 0 3
6
0 0 3 3 0 0
【输出样例】
1
0
1
0
【数据规模与约定】
对于20%的数据,有1<=n<=15,
对于50%的数据,有1<=n<=100,
对于100%的数据,有1<=n<=1000,1<=T<=50,输入数据中每个答案序列一定由某一组合法的座位分配方案生成。
题目分析
这道题让我产生了topsort的冲动。然后我成功的证明了我是个傻逼。这一题不难,但是很难想出来。从一个残缺的数列里面确定一个数列。我们注意到了key number就是不是零的数,如果当前的数字不同,我们就得出是两个不同的小组,如果相同,不能得到这个结论。如果我们找到的数字恰好把中间的空余部分填满,我们就从前一个地方更新答案。所以用一个数组来记录到i为止出现的可能排列,暴力枚举转移方程即可,
#include<bits/stdc++.h> using namespace std; #define RE register int #define N 1001 #define IL inline int T,n,a[N],f[N]; signed main(){ freopen("group.in","r",stdin),freopen("group.out","w",stdout); cin>>T; while(T--){ cin>>n; for (RE i=1;i<=n;++i) cin>>a[i]; memset(f,0,sizeof f),f[0]=1; for (RE i=1;i<=n;++i){ for (RE x=0,j=i;j;--j){ if (a[j]){ if (x&&a[j]^x) break; x=a[j]; }if (!x||i-j+1==x) if ((f[i]=min(2,f[j-1]+f[i]))==2) break; } } if (f[n]==1) cout<<1<<"\n"; else cout<<0<<"\n"; } }
代码说明
f[0]=1,这个不要忘记了啊。有两种ker number或者是不能填坑就不更新,否则我们更新答案,只有0,1,2这些可能。
我经过详细的调查后,得到了结论。我们班的一对小情侣因为太招摇被家长发现了,然后他们改用手机交流,变成了地下党没人知道。才谈了半年就要分了,如果女方会写函数式可持久化区间查找区间修改的线段式高级树形数据结构,他们就知道这个要持久化。
读者:尼玛,说主席树会死啊。
我:下回分解。。。