Nowcoder 提高组练习赛-R1
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的更多相关文章
- Nowcoder 提高组练习赛-R7
Nowcoder 提高组练习赛-R7 https://www.nowcoder.com/acm/contest/179#question 中间空了两场,因为实在是太难了... 第五场的第二题好像还比较 ...
- Nowcoder 提高组练习赛-R3
https://www.nowcoder.com/acm/contest/174#question 今天的题好难呀,只有94个人有分.然后我就爆零光荣 考到一半发现我们班要上物理课,还要去做物理实验( ...
- Nowcoder 提高组练习赛-R2
https://www.nowcoder.com/acm/contest/173#question T1:https://www.nowcoder.com/acm/contest/173/A 题意概述 ...
- nowcoder 提高组模拟赛 选择题 解题报告
选择题 链接: https://www.nowcoder.com/acm/contest/178/B 来源:牛客网 题目描述 有一道选择题,有 \(a,b,c,d\) 四个选项. 现在有 \(n\) ...
- nowcoder 提高组模拟赛 最长路 解题报告
最长路 链接: https://www.nowcoder.com/acm/contest/178/A 来源:牛客网 题目描述 有一张 \(n\) 个点 \(m\) 条边的有向图,每条边上都带有一个字符 ...
- nowcoder提高组2题解
T1 化一下试子就ok code #include<cstdio> #include<algorithm> inline long long read() { long lon ...
- Codevs 3287 货车运输 2013年NOIP全国联赛提高组(带权LCA+并查集+最大生成树)
3287 货车运输 2013年NOIP全国联赛提高组 时间限制: 1 s 空间限制: 128000 KB 题目等级 : 钻石 Diamond 传送门 题目描述 Description A 国有 n 座 ...
- 牛客网NOIP赛前集训营-提高组(第四场)B区间
牛客网NOIP赛前集训营-提高组(第四场)B区间 题目描述 给出一个序列$ a_1 \dots a_n$. 定义一个区间 \([l,r]\) 是好的,当且仅当这个区间中存在一个 \(i\),使得 ...
- NOIP2018初赛总结(提高组)(试题+答案+简要解析)
NOIP2018初赛总结(提高组) 更新完毕(纯手敲),如果有错误请在下面留言 单选题 T1.下列四个不同进制的数中,与其它三项数值上不相等的是 A.\((269)_{16}\) B.\((617)_ ...
随机推荐
- SQl语句查询性能优化
[摘要]本文从DBMS的查询优化器对SQL查询语句进行性能优化的角度出发,结合数据库理论,从查询表达式及其多种查询条件组合对数据库查询性能优化进行分析,总结出多种提高数据库查询性能优化策略,介绍索引的 ...
- SpringCloud微服务架构第三篇
原文链接:https://www.javazhiyin.com/5130.html 微服务开发专栏:https://www.javazhiyin.com/category/springcloud Ri ...
- C#生成二维码,裁切边框
使用google zxing生成的二维码带有白色边框,显示在报告(使用Crystal Report 水晶报表)上时,由于空间有限造成二维码过小难以扫描识别. 通过将白色边框裁切掉,可以在有限的空间内最 ...
- Jquery封装(学习)01
1.在开发过程中,我们有时候会经常用到重复的jquey代码,最常见的是我们那里需要就再哪里复制粘贴,这样大大增加了冗余代码,维护起来也不方便.我们何不把共同的jquery代码封装起来,哪里需要就哪里调 ...
- python-命令模式
源码地址:https://github.com/weilanhanf/PythonDesignPatterns 说明: 命令在发送方被激活,而在接收方被响应.一个对象既可以作为命令的发送方,也可以作为 ...
- WEB服务器、应用程序服务器、HTTP服务器的区别
WEB服务器.应用程序服务器.HTTP服务器的区别 Web服务器: 基本功能就是提供Web信息浏览服务.它只需支持HTTP协议.HTML文档格式及URL.与客户端的网络浏览器配合.因为Web服务器主要 ...
- 【代码笔记】iOS-4个可以单独点击的button
一,效果图. 二,工程图. 三,代码. ViewController.m #import "ViewController.h" @interface ViewController ...
- es6 类 和构造函数
- Javascript、Jquery获取浏览器和屏幕各种高度宽度[mark]
Javascript: IE中:document.body.clientWidth ==> BODY对象宽度document.body.clientHeight ==> BODY对象高度d ...
- 在ActiveReports页面报表中显示Google地图
有些报表需求中需要我们显示国家.城市等地址信息,在报表中添加地图信息会让报表给最终用户代码更多有效信息. 在报表中可以将地图作为图片添加进来,当一个图片显示在报表中时,该图片必须存放到本地计算机或者服 ...