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. Extjs4处理后台json数据中日期和时间的方法

    当ASP.NET后台使用JavaScriptSerializer这个组件将对象序列化为json,或者使用ScriptMethod特性的json [ScriptMethod(ResponseFormat ...

  2. 学习Memcached:2基本应用之控制台使用

    1.首先新建一个控制台应用. 2.将下载好需要引用的Memcached的Dll导入进来. 3.前期准备工作就结束了,其实很简单,memcache的配置使用是挺简单.下面就是写代码了. using Me ...

  3. java多线程框架

    JDK5中的一个亮点就是将Doug Lea的并发库引入到Java标准库中.Doug Lea确实是一个牛人,能教书,能出书,能编码,不过这在国外还是比较普遍的,而国内的教授们就相差太远了. 一般的服务器 ...

  4. Linux进程间的通信方式和原理

    进程的概念 进程是操作系统的概念,每当我们执行一个程序时,对于操作系统来讲就创建了一个进程,在这个过程中,伴随着资源的分配和释放.可以认为进程是一个程序的一次执行过程. 进程通信的概念 进程用户空间是 ...

  5. Maven的配置与下载

    一丶下载 前提条件 :已经安装配置好了Jdk 进入maven官网选择自己看上的版本:http://maven.apache.org/ 下载后解压开始配置环境! 二丶配置环境变量 新建系统变量 其实不建 ...

  6. 【JVM】2、JVM调优总结

    转自:http://unixboy.iteye.com/blog/174173/ 堆大小设置JVM 中最大堆大小有三方面限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内 ...

  7. Java三大特性:封装,继承,多态

    java提高篇(一)-----理解java的三大特性之封装 概念: 封装从字面上来理解就是包装的意思,专业点就是信息隐藏,是指利用抽象数据类型将数据和基于数据的操作封装在一起,使其构成一个不可分割的独 ...

  8. HDU3440(差分约束)

    House Man Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total S ...

  9. pycharm虚拟环境

    pycharm虚拟环境 1. 选择一个本地的空目录,---该目录就作为python虚拟环境目录, 2. 选择本地python安装目录: 3. 勾选该选项后则可以使用base interpreter中的 ...

  10. 【代码笔记】iOS-json文件的两种解析方式

    一,工程图. 二,代码. #import "ViewController.h" #import "SBJson.h" @interface ViewContro ...