前言
好久没考过试了,居然考这么挫qwq。。。
T1 water
题目描述
给出1~n的一个排列,统计该排列有多少个长度为奇数的连续子序列的中位数是b。
中位数是指把所有元素从小到大排列后,位于中间的数。(来源:[CQOI2009]中位数)
【数据规模】
对于30%的数据中,满足n≤100;
对于60%的数据中,满足n≤1000;
对于100%的数据中,满足n≤100000,1≤b≤n。
考试分析
emmm....不是说好第一题是水题吗?我觉得再怎么模拟也只有O(n^2)啊!
肯定TM又是一道找规律题..............推了1h居然没退出来,wc,果断60分滚粗
正解
(ps:思路来自lsq大佬)
1. 首先开一个sum[ ]数组、一个变量q,线性扫一遍,
如果a[i]>b,则++q;如果a[i]
接着令sum[i]=q(sum[i]表示从i+1开始匹配还差sum[i]个比b小的数 )
2. 接着开一个f[ ][2]数组,并初始化f[0][0]=1;
从1扫到pos-1,
如果i是偶数,则++f[sum[i]][0];否则++f[sum[i][1];
然后从pos+1扫到n开始匹配
如果i是偶数,因为中间有个b,所以奇偶性要变,则ans+=f[sum[i]][1];否则ans+=f[sum[i]][0];
3. 最后输出ans即可
Code
#include
using namespace std;
templateinline void read(TP & x)
{
x=0;int f=1;register char c=getchar();
while(c<'0'||c>'9') if(c=='-') f=-1;c=getchar();
while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
x*=f;
}
templateinline void print(TP x)
{
if(x<0) x=-x,putchar('-');
if(x>9) print(x/10);
putchar(x%10+'0');
}
int n,b,sum[1000005],ans,pos,qwq,a[1000005],f[1000005][2];
int main()
{
freopen("water.in","r",stdin);
freopen("water.out","w",stdout);
read(n),read(b);
for(int i=1;i<=n;++i) read(a[i]);
for(int i=1;i<=n;++i)
{
if(a[i]>b) ++qwq;
else if(a[i]
T2 str
题目描述
已知有两个字串$A,B$及一组字串变换的规则(至多$6$个规则):
$A_1$ ->$ B_1$
$A_2$ -> $B_2$
规则的含义为:在 $A$中的子串 $A_1$ 可以变换为$ B_1$,$A_2$ 可以变换为 $B_2$ …。
例如:$A$='$abcd$'$B$='$xyz$'
变换规则为:
‘$abc$’->‘$xu$’‘$ud$’->‘$y$’‘$y$’->‘$yz$’
则此时,$A$可以经过一系列的变换变为$B$,其变换的过程为:
‘$abcd$’->‘$xud$’->‘$xy$’->‘$xyz$’
共进行了$3$次变换,使得$A$变换为$B$。
所有字符串长度的上限为$20$。
若在$10$步(包含$10$步)以内能将$A$变换为$B$,则输出最少的变换步数;否则输出"NO ANSWER!"
(来源:NOIP2002 字符变换)
考试分析
正解
题解传送门(by me)
T3 tree