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)_ ...
随机推荐
- 【Java深入研究】3、HashMap源码解析(jdk 1.7)
1. HashMap的数据结构 数据结构中有数组和链表来实现对数据的存储,但这两者基本上是两个极端. 数组 数组存储区间是连续的,占用内存严重,故空间复杂的很大.但数组的二分查找时间复杂度小,为O(1 ...
- 利用JavaMail发送邮件:smtp.163.com
一.利用JavaMail发送邮件案例: 1.maven项目结构: 2.先在pom.xml里边加入Javamail依赖,系统会根据坐标自动下载mail包(前提是配置好了maven): 3.配置email ...
- 杭电acm习题分类
专注于C语言编程 C Programming Practice Problems (Programming Challenges) 杭电ACM题目分类 基础题:1000.1001.1004.1005. ...
- vue中的js引入图片,必须require进来
需求:如何components里面的index.vue怎样能把assets里面的图片拿出来. 1.在img标签里面直接写上路径: <img src="../assets/a1.png& ...
- JavaScriptDOM操作那些事儿
查询: ①.标准DOM操作API: document.getElementById. document.getElementsByTagName. document.getElementsByName ...
- Gruntfile.js文件配置项
GRUNT安装与配置 Posted on 2016-08-19 18:13 听风吹来的种子 阅读(47) 评论(0) 编辑 收藏 安装 CLI npm install -g grunt-cli//全局 ...
- 【代码笔记】iOS-plist获得城市列表
一,工程图. 二,代码. - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the ...
- 华为5G折叠屏幕适配
华为5G折叠屏幕的发布,迎来新的一个设备——移动端的折叠设备华为Max;华为Max设备分辨率有以下几种 8.0,6.8,6.38,这三种场景下页面展示都是不一样的表现,需要我们在开发中注意监听屏幕变化 ...
- [iOS] 列表滑动展开隐藏头部HeaderView
平常遇到大多数的带有列表的应用都会遇到这个场景:在列表顶端有一个Header,当向上滑动列表时,压缩header,向下滑动列表到头时,展开header.这种样式在例如微博,twitter这些展示动态的 ...
- (Stanford CS224d) Deep Learning and NLP课程笔记(二):word2vec
本节课将开始学习Deep NLP的基础--词向量模型. 背景 word vector是一种在计算机中表达word meaning的方式.在Webster词典中,关于meaning有三种定义: the ...