您的位置:首页 > 其它

2017.09.23【NOIP提高组】模拟赛B组

2017-09-23 16:29 232 查看
第二题竟然没有打到30,只得了20。

第三题看到数据30分n<=5应该手推的。

100+20+5=125。

小结

T1:【NOIP2013模拟联考10】密码(substring)

https://jzoj.net/senior/#contest/show/2145/0

可以看到30分就直接暴力,100就只用把暴力转化成找开头,然后往后一个一个跳。就可以了。把一个一个计算改成组合乘法。

T2:【NOIP2013模拟联考10】独立集(bubble)

https://jzoj.net/senior/#contest/show/2145/1

我们很简单可以发现,这是一个最长不下降子序列,因为只有最长不下降子序列里面的数再冒泡交换时不会交换,也就是不会连边,所以第一问就是最长不下降子序列。

第二问呢,我们就可以考虑前面做一个最长不下降子序列,又从后面做一个最长下降子序列,两个的交集就是答案了。

我们可以处理num1[i]表示取i时[1..i]的最长不下降子序列,num2[i]表示取i时[i..n]的最长下降子序列。发现如果num1[i]+num2[i]-1=s(就是答案)时,这个数就是成立的。

但是为了防止,在两种方法里一个有a没b,一个有b没a。我们用一个bz[i]表示i这个长度的最长不下降子序列出现的次数。如果合法而且出现次数为1,那么就输出。

#include<cstdio>
#include<iostream>
using namespace std;
int f1[100005],f2[100005];
int num1[100005],num2[100005];
int n,a[100005],maxn,b[100005];
int bz[100005],ans[100005];
int main()
{
scanf("%d",&n);
int i,j,l,r,mid;
for (i=1;i<=n;++i)
{
scanf("%d",&a[i]);
b[i]=-a[i];
}
f1[0]=0;f2[0]=0;
for (i=1;i<=n;++i)
{
if(a[i]>f1[f1[0]])
{
f1[++f1[0]]=a[i];
num1[i]=f1[0];
}
else
{
l=1;r=f1[0];
while(l<r)
{
mid=(l+r)/2;
if(f1[mid]>a[i])r=mid;
else l=mid+1;
}
f1[l]=a[i];
num1[i]=l;
}
maxn=max(maxn,f1[0]);
}
for (i=n;i>=1;--i)
{
if(b[i]>f2[f2[0]]||f2[0]==0)
{
f2[++f2[0]]=b[i];
num2[i]=f2[0];
}
else
{
l=1;r=f2[0];
while(l<r)
{
mid=(l+r)/2;
if(f2[mid]>b[i])r=mid;
else l=mid+1;
}
f2[l]=b[i];
num2[i]=l;
}
}
printf("%d\n",maxn);
ans[0]=0;
for (i=1;i<=n;++i)
if(num1[i]+num2[i]-1==maxn)
{
++ans[0];
ans[ans[0]]=i;
bz[num1[i]]++;
}
for (i=1;i<=ans[0];++i)
if(bz[num1[ans[i]]]==1) printf("%d ",ans[i]);
}


T3:【NOIP2014八校联考第4场第2试10.20】准备复赛(exam)

https://jzoj.net/senior/#contest/show/2145/2

树形DP?
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: