https://www.nowcoder.com/acm/contest/172#question

  单人报名300元,五人合报免费,于是就和学弟同学学长们组了一个三世同堂的队伍,高一的学长wzhqwq;同一届的同学们:zutter,asuldb;以及不是学长却胜似学长的qwaszx。

  感觉这套题比NOIP还是要难一些的。

  A:中位数:https://www.nowcoder.com/acm/contest/172/A

  题意概述:给定一个长度为$n$的序列,求它的所有长度大于等于$len$的子序列的中位数的最大值。$n,len<=10^5$

  NOIP的D1T1不应该是签到题吗...?这个题非常清奇啊。想了半小时(中间电脑死机2次)之后发现自己确实不会做,就写了一个$O(N^2logN)$的对顶堆做法,拿分倒是非常稳,确实得了60。

  

 # include <cstdio>
# include <iostream>
# include <queue>
# define R register int using namespace std; const int maxn=;
int n,len,ans=;
int a[maxn];
priority_queue <int,vector<int> > q1;
priority_queue <int,vector<int>,greater<int> > q2; int read()
{
int x=,f=;
char c=getchar();
while (!isdigit(c)) { if(c=='-') f=-f; c=getchar(); }
while (isdigit(c)) { x=(x<<)+(x<<)+(c^); c=getchar(); }
return x*f;
} int ask()
{
if(q1.size()<q2.size())
return q2.top();
return q1.top();
} int main()
{
n=read(),len=read();
for (R i=;i<=n;++i)
a[i]=read();
for (R i=;i<=n;++i)
{
if(i+len->n) break;
while (q1.size()) q1.pop();
while (q2.size()) q2.pop();
q1.push(-);
q2.push();
for (R j=i;j<=n;++j)
{
if(a[j]<q2.top()) q1.push(a[j]);
else q2.push(a[j]);
while (q1.size()<q2.size())
{
q1.push(q2.top());
q2.pop();
}
while (q2.size()<q1.size())
{
q2.push(q1.top());
q1.pop();
}
if(j-i+>=len) ans=max(ans,ask());
}
}
printf("%d",ans);
return ;
}

中位数(60pts)

  现在来说一下正解:虽然答案本身并不单调,然而有一个东西是显而易见非常单调的:设$f_x=[ans>=x]$,这是一个布尔函数,它是单调的。所以二分这个答案,接下来考虑怎么$check$。离散化,大于等于$x$的设置成$1$,小于$x$的设成$-1$,如果一段长度大于$len$的区间的和大于$0$,就说明$f_x=true$。注意这里一定不能写成大于等于,因为这个$x$不一定是这个序列中真实存在的数,如果比它大,比它小的数一样多,这时的中位数是有可能小于$x$的(偶数长度的序列取小一点的那个值)。接下来的问题是怎么判断是否有区间的和大于$0$,其实就是求一段长度大于等于len的区间的和的最大值,用类似于单调队列优化dp的思想即可,不过只需要维护一个最小值。

  

 # include <cstdio>
# include <iostream>
# include <queue>
# define R register int using namespace std; const int maxn=;
int n,len,ans=;
int a[maxn],b[maxn];
int s[maxn],minn[maxn],maxx=; int read()
{
int x=,f=;
char c=getchar();
while (!isdigit(c)) { if(c=='-') f=-f; c=getchar(); }
while (isdigit(c)) { x=(x<<)+(x<<)+(c^); c=getchar(); }
return x*f;
} bool check (int x)
{
for (R i=;i<=n;++i)
if(a[i]<x) b[i]=-;
else b[i]=;
for (R i=;i<=n;++i)
s[i]=s[i-]+b[i];
minn[]=s[];
for (R i=;i<=n;++i)
minn[i]=min(minn[i-],s[i]);
for (R i=len;i<=n;++i)
if(s[i]>minn[i-len])
return true;
return false;
} int main()
{
n=read(),len=read();
for (R i=;i<=n;++i)
a[i]=read(),maxx=max(maxx,a[i]);
int mid,ans=,l=,r=maxx;
while (l<=r)
{
mid=(l-r)/+r;
if(check(mid))
ans=max(ans,mid),l=mid+;
else
r=mid-;
}
printf("%d",ans);
return ;
}

中位数

  B.数数字:https://www.nowcoder.com/acm/contest/172/B

  题意概述:对于一个数$x$,定义$f_x$为$x$的各个数位的乘积。对于$L<=x<=R$,问有多少$x$满足,$L_1<=f_x<=R_1$。

  $0<=L,R,L_1,R_1 <= 10^18,L<=R,L_1<=R_1$

  暴力可以得好多分,如果注意特判l=0的情况就会有50分的好成绩,但是考试时忘了这种问题所以只有45。正解是分解质因数的数位dp。

  

 # include <cstdio>
# include <iostream>
# define R register int using namespace std; int l,r,ll,rr,ans;
int x,s; int read()
{
int x=,f=;
char c=getchar();
while (!isdigit(c)) { if(c=='-') f=-f; c=getchar(); }
while (isdigit(c)) { x=(x<<)+(x<<)+(c^); c=getchar(); }
return x*f;
} int main()
{
scanf("%d%d%d%d",&l,&r,&ll,&rr);
for (int i=l;i<=r;++i)
{
s=;
x=i;
if(x==) s=;
while (x)
{
s*=x%;
x/=;
}
if(ll<=s&&s<=rr) ans++;
}
printf("%d",ans);
return ;
}

数数字(50pts)

  C.保护:https://www.nowcoder.com/acm/contest/172/C

  题意概述:给定一颗$n$个点的树,以及$m$条路径,多组询问:给出一组$u$,$k$,询问从u到根的路径上满足(从$u$到$p$的路径整体都被至少k条路径覆盖过)的深度最浅的点$p.n,m,q<=200000$

  解释一下,$u->p$路径被路径$x$覆盖当且仅当$u->p$这段路径上的每一条边都属于路径$x$.

  看到这道题就觉得非常像天天爱跑步。想到了一个最差能到$O(q*max(n,m))$的算法,只得了$40$。这个做法是这样的,对于每一条路径首先求出它的$lca$,用$n$个$vector$,在每条路径的两个端点分别$push$一个编号进去,在$lca$处$push$一个编号的相反数,表示从这里再往上就不再有这条路径了。如果一条$u->p$路径被路径$x$所覆盖,则$x$必然有一个端点在$u$的子树内,而且它的$lca$不能在$p$的子树内。这样首先从$u$点向下递归,用一个$bitset$作为桶,统计有哪些路径覆盖了点u,再向上爬,每走一步就把$lca$在这里的路径删除去掉,直到路径的数目小于$k$为止。 

  

 # include <cstdio>
# include <iostream>
# include <vector>
# include <bitset>
# define R register int using namespace std; const int maxn=;
int q,u,k,n,m,x,y,lca[maxn],s[maxn],t[maxn],cnt,dep[maxn],F[maxn][];
int firs[maxn],h,ans;
vector<int> v[maxn];
bitset <maxn> T;
struct edge
{
int too,nex;
}g[maxn<<]; int read()
{
int x=,f=;
char c=getchar();
while (!isdigit(c)) { if(c=='-') f=-f; c=getchar(); }
while (isdigit(c)) { x=(x<<)+(x<<)+(c^); c=getchar(); }
return x*f;
} void add (int x,int y)
{
g[++h].too=y;
g[h].nex=firs[x];
firs[x]=h;
} void dfs (int x)
{
int j;
for (R i=firs[x];i;i=g[i].nex)
{
j=g[i].too;
if(dep[j]) continue;
dep[j]=dep[x]+;
F[j][]=x;
for (R i=;i<=;++i)
F[j][i]=F[ F[j][i-] ][i-];
dfs(j);
}
} void dfs1 (int x)
{
int j,siz=v[x].size();
for (R i=;i<siz;++i)
if(v[x][i]>&&T[ v[x][i] ]==)
cnt++,T[ v[x][i] ]=;
for (R i=firs[x];i;i=g[i].nex)
{
j=g[i].too;
if(dep[j]<dep[x]) continue;
dfs1(j);
}
if(x==u) return;
for (R i=;i<siz;++i)
if(v[x][i]<&&T[ -v[x][i] ]==)
cnt--,T[ -v[x][i] ]=;
} inline int LCA (int x,int y)
{
if(dep[x]>dep[y]) swap(x,y);
for (R i=;i>=;--i)
if(dep[y]-(<<i)>=dep[x]) y=F[y][i];
if(x==y) return x;
for (R i=;i>=;--i)
if(F[x][i]!=F[y][i]) x=F[x][i],y=F[y][i];
return F[x][];
} void up (int x)
{
if(cnt<k) return ;
ans=dep[u]-dep[x];
int siz=v[x].size();
for (R i=;i<siz;++i)
if(v[x][i]<&&T[ -v[x][i] ]==)
cnt--,T[ -v[x][i] ]=;
up(F[x][]);
} int main()
{
scanf("%d%d",&n,&m);
for (R i=;i<n;++i)
{
x=read();
y=read();
add(x,y);
add(y,x);
}
dep[]=;
dfs();
for (R i=;i<=m;++i)
{
s[i]=read();
t[i]=read();
lca[i]=LCA(s[i],t[i]);
v[ s[i] ].push_back(i);
v[ t[i] ].push_back(i);
v[ lca[i] ].push_back(-i);
}
scanf("%d",&q);
for (R i=;i<=q;++i)
{
T.reset();
cnt=,ans=;
u=read();
k=read();
dfs1(u);
up(u);
printf("%d\n",ans);
}
return ;
}

保护(40pts)

  

  最后放一张惨淡的成绩,下次要加油啦 (在nowcoder,享受一场上蓝的快乐)

---shzr

Nowcoder 提高组练习赛-R1的更多相关文章

  1. Nowcoder 提高组练习赛-R7

    Nowcoder 提高组练习赛-R7 https://www.nowcoder.com/acm/contest/179#question 中间空了两场,因为实在是太难了... 第五场的第二题好像还比较 ...

  2. Nowcoder 提高组练习赛-R3

    https://www.nowcoder.com/acm/contest/174#question 今天的题好难呀,只有94个人有分.然后我就爆零光荣 考到一半发现我们班要上物理课,还要去做物理实验( ...

  3. Nowcoder 提高组练习赛-R2

    https://www.nowcoder.com/acm/contest/173#question T1:https://www.nowcoder.com/acm/contest/173/A 题意概述 ...

  4. nowcoder 提高组模拟赛 选择题 解题报告

    选择题 链接: https://www.nowcoder.com/acm/contest/178/B 来源:牛客网 题目描述 有一道选择题,有 \(a,b,c,d\) 四个选项. 现在有 \(n\) ...

  5. nowcoder 提高组模拟赛 最长路 解题报告

    最长路 链接: https://www.nowcoder.com/acm/contest/178/A 来源:牛客网 题目描述 有一张 \(n\) 个点 \(m\) 条边的有向图,每条边上都带有一个字符 ...

  6. nowcoder提高组2题解

    T1 化一下试子就ok code #include<cstdio> #include<algorithm> inline long long read() { long lon ...

  7. Codevs 3287 货车运输 2013年NOIP全国联赛提高组(带权LCA+并查集+最大生成树)

    3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description A 国有 n 座 ...

  8. 牛客网NOIP赛前集训营-提高组(第四场)B区间

    牛客网NOIP赛前集训营-提高组(第四场)B区间 题目描述 给出一个序列$ a_1  \dots   a_n$. 定义一个区间 \([l,r]\) 是好的,当且仅当这个区间中存在一个 \(i\),使得 ...

  9. NOIP2018初赛总结(提高组)(试题+答案+简要解析)

    NOIP2018初赛总结(提高组) 更新完毕(纯手敲),如果有错误请在下面留言 单选题 T1.下列四个不同进制的数中,与其它三项数值上不相等的是 A.\((269)_{16}\) B.\((617)_ ...

随机推荐

  1. MVC的注意事项及开发技巧

    演示产品源码下载地址:http://www.jinhusns.com 

  2. (转) C# Async与Await的使用

    (转) C# Async与Await的使用 class Program { static void Main(string[] args) { Console.WriteLine("主线程测 ...

  3. .net Core 部署到 Linux

    1.环境说明 服务器系统:CentOS 7.4  64位 相关工具:Xshel.Xftp .net Core版本:2.2 VS版本:2017 服务器软件软件:.netcore.nginx.superv ...

  4. Thinkphp 全选、反选 批量删除

    完整案例 前台 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www ...

  5. JS 获取css transform中的值

    可以参考这位博主的文章https://www.cnblogs.com/zhenwoo/p/4993780.html 不想看直接想看怎么解决的看这: var translates= document.d ...

  6. 3.配置Spring+SpringMvc+Mybatis(分库or读写分离)--Intellij IDAE 2016.3.5

    作者QQ:1095737364    QQ群:123300273     欢迎加入! 建立好maven多模块项目后,开始使用ssm传统的框架:http://www.cnblogs.com/yysbol ...

  7. css语法和基本知识

    1.CSS全称为“层叠样式表”,它主要是用于定义HTML内容在浏览器内的显示样式,如文字大小.颜色.字体加粗等. 注:使用CSS样式的一个好处是通过定义某个样式,可以让不同网页位置的文字有着统一的字体 ...

  8. PHP 基础总结

    PHP(Hypertext Preprocessor)是一种被广泛应用的开源通用脚本语言,尤其适用于Web开发.可用于服务端脚本.命令行脚本.桌面应用程序三大领域. PHP 的 SAPI(服务器应用程 ...

  9. [性能调优]在PeopleSoft中使用函数索引

    那些没有在PeopleSoft系统遇到性能问题的人,特别是基于Oracle数据库的PeopleSoft,可能不知道基于函数的索引. 根据定义,基于函数的索引是使用如下方法定义的: 基于表达式,例如算术 ...

  10. php递归获取无限分类菜单

    从数据库获取所有菜单信息,需要根据id,pid字段获取主菜单及其子菜单,以及子菜单下的子菜单,可以通过函数递归来实现. <?php class Menu { public $menu = arr ...