noip模拟测试21
考试总结:这次考试,前两道题的题面描述不是很清楚,导致我不知道输出格式到底是什么,挂了差不多80分(好多人也是这样),总体来说,这次考试的前两道题暴力分是打满了,最后一道题打了一个假的暴搜,在考场上没调出来,代码能力还需提高。
T1 Median
思路:我们首先利用线性筛求出我们需要的素数,然后求出整个序列,接下来我们考虑计算中位数,首先明确一个问题,这中位数是将区间里的数从大到小排好序之后的中间的那个数,(我当时因为这个调了老半天),之后我们注意到这个区间长度是一个定值,每次移动只会有两个值出现的次数发生变化,那我们就可以利用一个桶,记录每个数出现的次数,然后维护一个指针指向中位数的位置,当我们移动的时候,相应的更新指针的位置,具体实现见代码:
AC_Code
#include<bits/stdc++.h>
#define re register int
#define ii inline int
#define iv inline void
using namespace std;
const int M=2e7+10;
const int G=1e7+10;
const int P=1e8+8e7;
double ans;
int n,k,w,sum,ls;
int s1[M],s2[M],pr[G],u[G],tong[M];
bool ifs[P];
ii read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=0;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return (f)?x:(-x);
}
iv get_prime()
{
for(re i=2;sum<=G;i++)
{
if(!ifs[i])
{
pr[++sum]=i;
}
for(re j=1;j<=sum&&i*pr[j]<=P;j++)
{
ifs[i*pr[j]]=1;
if(i%pr[j]==0)
break;
}
}
for(re i=1;i<=n;i++)
s1[i]=1ll*pr[i]%w*i%w;
for(re i=1;i<=n;i++)
s2[i]=1ll*s1[i]+s1[i/10+1];
}
int my(int a,int b)
{
return a<b;
}
iv solve1()
{
long long mid;
for(re i=1;i<=k;i++)
{
u[i]=s2[i];
tong[s2[i]]++;
}
sort(u+1,u+k+1,my);
mid=u[(k+1)/2];
ls=upper_bound(u+1,u+k+1,mid)-u-1;
ans+=mid;
for(re i=2;i<=n-k+1;i++)
{
tong[s2[i-1]]--;
tong[s2[i+k-1]]++;
if(s2[i-1]*1ll<=mid)
ls--;
if(s2[i+k-1]*1ll<=mid)
ls++;
while(1)
{
if(1ll*(ls-tong[mid])>=((k+1)/2))
{
ls-=tong[mid];
mid--;
}
else if(1ll*(k-ls)>=((k+1)/2))
{
mid++;
ls+=tong[mid];
}
if((ls-tong[mid]<((k+1)/2))&&(k-ls<((k+1)/2)))
break;
}
ans+=mid;
}
printf("%.1lf\n",(double)ans);
}
iv solve2()
{
double mid;
long long l1,l2,m1,m2;
for(re i=1;i<=k;i++)
{
u[i]=s2[i];
tong[s2[i]]++;
}
sort(u+1,u+k+1,my);
mid=((double)u[k/2]+(double)u[k/2+1])/(double)2;
l1=upper_bound(u+1,u+k+1,u[k/2])-u-1;
l2=upper_bound(u+1,u+k+1,u[k/2+1])-u-1;
m1=u[k/2];
m2=u[k/2+1];
ans+=mid;
for(re i=2;i<=n-k+1;i++)
{
tong[s2[i-1]]--;
tong[s2[i+k-1]]++;
if(s2[i-1]<=m1)
{
l1--;
}
if(s2[i-1]<=m2)
{
l2--;
}
if(s2[i+k-1]<=m1)
{
l1++;
}
if(s2[i+k-1]<=m2)
{
l2++;
}
while(l1-tong[m1]>=(k/2))
{
l1-=tong[m1];
--m1;
}
while(l1+tong[m1+1]<(k/2))
{
++m1;
l1+=tong[m1];
}
if(l1<(k/2))
{
++m1;
l1+=tong[m1];
}
while(l2-tong[m2]>=(k/2+1))
{
l2-=tong[m2];
m2--;
}
while(l2+tong[m2+1]<(k/2+1))
{
++m2;
l2+=tong[m2];
}
if(l2<(k/2+1))
{
++m2;
l2+=tong[m2];
}
ans+=((double)m1+(double)m2)/(double)2;
}
long long out=ans;
if((ans-(double)out)==0.5)
printf("%.1lf\n",(double)out+0.5);
else
printf("%.1lf\n",(double)out);
}
signed main()
{
n=read();
k=read();
w=read();
get_prime();
if(k&1)
solve1();
else
solve2();
/*long long out=ans;
if((ans-(double)out)==0.5)
printf("%.1lf\n",(double)out+0.5);
else
printf("%.1lf\n",(double)out);*/
return 0;
}
T2 Game
思路:因为根据最优策略,如果我要放进去的球比当前序列的最大值还要大,那么我直接就把它拿走了,就不把它放入序列了,所以,如果我们维护一个指向当前序列最大值的指针,那么这个指针显然是单调递减的,我们每次操作后维护这个指针即可,具体实现见代码:
AC_Code
#include<bits/stdc++.h>
#define re register int
#define lc rt<<1
#define rc rt<<1|1
#define mid ((l+r)>>1)
#define re register int
#define ii inline int
#define iv inline void
using namespace std;
const int N=1e5+10;
int n,k,p,cnt,num,mx,use;
int a[N],b[N];
long long tong[N];
long long A,B,la,lb;
ii read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=0;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return (f)?x:(-x);
}
iv change()
{
if(!tong[mx])
{
while(1)
{
mx--;
if(tong[mx]||(mx<=0))
break;
}
}
}
int main()
{
n=read();
k=read();
for(re i=1;i<=n;i++)
a[i]=read();
for(re i=1;i<=k;i++)
{
p=read();
A=0;
B=0;
la=-1;
lb=-1;
cnt=0;
mx=-1;
use=0;
bool pd;
memset(tong,0,sizeof(tong));
for(re j=1;j<=n;j++)
{
while(j<=p&&j<=n)
{
tong[a[j]]++;
mx=max(mx,a[j]);
j++;
}
pd=0;
cnt=j-1;
while(1)
{
if(pd==0||cnt>=n)
{
change();
A+=mx;
tong[mx]--;
change();
}
else if(cnt<n)
{
++cnt;
if(a[cnt]>=mx)
{
A+=a[cnt];
}
else if(tong[mx])
{
A+=mx;
tong[a[cnt]]++;
tong[mx]--;
change();
}
else
{
tong[a[cnt]]++;
change();
A+=mx;
tong[mx]--;
change();
}
}
++use;
if(use==n)
break;
if(cnt<n)
{
++cnt;
if(a[cnt]>=mx)
{
B+=a[cnt];
}
else if(tong[mx])
{
B+=mx;
tong[a[cnt]]++;
tong[mx]--;
change();
}
else
{
tong[a[cnt]]++;
change();
B+=mx;
change();
}
}
else
{
change();
B+=mx;
tong[mx]--;
change();
}
++use;
if(use==n)
break;
if(la==A&&lb==B)
break;
la=A;
lb=B;
pd=1;
}
break;
}
printf("%lld\n",A-B);
}
return 0;
}
T3 Park
一道DP好题,思路:设\(dp_{0,i,j}\)表示我从 i 的子树走到i,一共撒了 j 次的最大差值,设 \(dp_{1,i,j}\)表示从 i的father
走向 i ,一共撒了 j 次的最大差值,那么状态转移方程可得 \(dp_{0,i,j}=max(dp_{0,i,j},max(dp_{0,son,j},dp_{0,son,j-1}+sum_i-p_{son}))\) ,\(dp_{1,i,j}=max(dp_{1,i,j},max(dp_{1,son,j},dp_{1,son,j-1}+sum_i-p_{father}))\)
但是,因为我们自上而下和自下而上计算可能会得到不一样的结果,所以我们还要反着做一遍DP
代码如下:
AC_Code
#include<bits/stdc++.h>
#define re register int
#define ii inline int
#define iv inline void
using namespace std;
const int N=1e5+10;
int n,v;
long long ans;
long long p[N],dp[2][N][110],sum[N];
vector<int> edge[N];
ii read()
{
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9')
{
if(ch=='-')
f=0;
ch=getchar();
}
while(ch>='0'&&ch<='9')
{
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return (f)?x:(-x);
}
iv dfs(int x,int f)
{
for(re i=1;i<=v;i++)
{
dp[0][x][i]=sum[x];
dp[1][x][i]=sum[x]-p[f];
}
for(re i=0;i<edge[x].size();i++)
{
if(edge[x][i]==f)
continue;
dfs(edge[x][i],x);
for(re j=1;j<v;j++)
ans=max(ans,dp[0][x][j]+dp[1][edge[x][i]][v-j]);
for(re j=1;j<=v;j++)
{
dp[0][x][j]=max(dp[0][x][j],max(dp[0][edge[x][i]][j],dp[0][edge[x][i]][j-1]+sum[x]-p[edge[x][i]]));
dp[1][x][j]=max(dp[1][x][j],max(dp[1][edge[x][i]][j],dp[1][edge[x][i]][j-1]+sum[x]-p[f]));
}
}
reverse(edge[x].begin(),edge[x].end());
for(re i=1;i<=v;i++)
{
dp[0][x][i]=sum[x];
dp[1][x][i]=sum[x]-p[f];
}
for(re i=0;i<edge[x].size();i++)
{
if(edge[x][i]==f)
continue;
for(re j=1;j<v;j++)
ans=max(ans,dp[0][x][j]+dp[1][edge[x][i]][v-j]);
for(re j=1;j<=v;j++)
{
dp[0][x][j]=max(dp[0][x][j],max(dp[0][edge[x][i]][j],dp[0][edge[x][i]][j-1]+sum[x]-p[edge[x][i]]));
dp[1][x][j]=max(dp[1][x][j],max(dp[1][edge[x][i]][j],dp[1][edge[x][i]][j-1]+sum[x]-p[f]));
}
}
for(re i=1;i<=v;i++)
ans=max(ans,max(dp[0][x][i],dp[1][x][i]));
}
signed main()
{
n=read();
v=read();
for(re i=1;i<=n;i++)
scanf("%lld",&p[i]);
int a,b;
for(re i=1;i<n;i++)
{
a=read();
b=read();
edge[a].push_back(b);
edge[b].push_back(a);
sum[a]+=p[b];
sum[b]+=p[a];
}
dfs(1,0);
printf("%lld\n",ans);
return 0;
}
noip模拟测试21的更多相关文章
- 2019.8.14 NOIP模拟测试21 反思总结
模拟测试20的还没改完先咕着 各种细节问题=错失190pts T1大约三分钟搞出了式子,迅速码完,T2写了一半的时候怕最后被卡评测滚去交了,然后右端点没有初始化为n…但是这样还有80pts,而我后来还 ...
- NOIP模拟测试21「折纸·不等式」
折纸 题解 考试时无限接近正解,然而最终也只是接近而已了 考虑模拟会爆炸,拿手折纸条试一试,很简单 考你动手能力 代码 #include<bits/stdc++.h> using name ...
- 2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci)
2019.8.3 [HZOI]NOIP模拟测试12 A. 斐波那契(fibonacci) 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 找规律 找两个节点的lca,需 ...
- 「题解」NOIP模拟测试题解乱写II(36)
毕竟考得太频繁了于是不可能每次考试都写题解.(我解释个什么劲啊又没有人看) 甚至有的题目都没有改掉.跑过来写题解一方面是总结,另一方面也是放松了. NOIP模拟测试36 T1字符 这题我完全懵逼了.就 ...
- 2019.8.3 [HZOI]NOIP模拟测试12 C. 分组
2019.8.3 [HZOI]NOIP模拟测试12 C. 分组 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 刚看这题觉得很难,于是数据点分治 k只有1和2两种,分别 ...
- 2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色
2019.8.3 [HZOI]NOIP模拟测试12 B. 数颜色 全场比赛题解:https://pan.baidu.com/s/1eSAMuXk 数据结构学傻的做法: 对每种颜色开动态开点线段树直接维 ...
- NOIP模拟测试19「count·dinner·chess」
反思: 我考得最炸的一次 怎么说呢?简单的两个题0分,稍难(我还不敢说难,肯定又有人喷我)42分 前10分钟看T1,不会,觉得不可做,完全不可做,把它跳了 最后10分钟看T1,发现一个有点用的性质,仍 ...
- NOIP模拟测试17&18
NOIP模拟测试17&18 17-T1 给定一个序列,选取其中一个闭区间,使得其中每个元素可以在重新排列后成为一个等比数列的子序列,问区间最长是? 特判比值为1的情况,预处理比值2~1000的 ...
- NOIP模拟测试1(2017081501)
好,今天是cgg第一次举行模拟测试,希望各位支持. 时间限制:2小时 题目链接: 题目一:水得都没名字了 题目二:车站 题目三:选数 不要觉得2小时太少,我的题目很良心,都很简单. 答案可以在模拟测试 ...
随机推荐
- Centos7安装部署搭建gitlab平台、汉化
Centos7安装部署搭建gitlab平台.汉化 安装环境要求:内存不要小于4G,否则后期web界面可能会报错 一.准备工作 1.1 查看系统版本 首先查询系统版本,下载Gitlab的对应版本 [ro ...
- Qt:报文接收不完成,产生分帧的处理方法
最近在设备的测试工装时,通过串口,向设备发送自定义规约,其报文的枕结构已经编写,使用串口助手调试,设备可正常回复,但是通过工装,接收报文会不完整,导致解析失败.使用qDebug打印出来却发现数据被分成 ...
- 温故知新,基于Nexus3和Docker搭建私有Docker Mirrors镜像库
前言 接着上一篇文章关于基于Nexus3和Docker搭建私有Nuget服务的探索,我们可以进一步利用Nexus3来创建一个私有的Docker镜像库满足内部需求. 仓库类型 hosted: 本地存储, ...
- Binding(五):多路绑定
Binding不止能绑定一个源,它还能绑定多个源,这就是我们这节要讲的多路绑定:MultiBinding. 使用多路绑定跟一般的绑定还是有区别的,首先它并不能很好的在标记扩展中使用,另外,使用多路绑定 ...
- Java Set HashSet
import java.util.HashSet; import java.util.Set; /** Set存储特点:数据无序.不可重复 Set接口的实现类: HashSet:Set接口的主要实现类 ...
- 超详细的原生JavaScript轮播图(幻灯片)的制作
本次轮播图的制作主要分为3个部分,分别是:设置定时器自动轮播:点击左右切换按钮轮播:下方点击按钮轮播.具体实现步骤如下: (效果图) html部分代码如下: <div class="s ...
- Linux:获取Linux离线postgresql数据库安装包并部署
获取离线安装包(方法一) 1. 进入官网:https://www.postgresql.org/ 2. 下载步骤 (1)点击Download (2) 选择安装的服务器的版本 (3)更新yum源 #更 ...
- centos下nodejs,npm的安装和nodejs的升级
安装: sudo yum install epel-release sudo yum install nodejs node -v yum install -y npm --enablerepo=ep ...
- IDA Pro 6.0使用Qt 框架实现了跨平台的UI
IDA Pro 6.0使用Qt 框架实现了跨平台的UI.它的好处是插件编写者还可以直接使用 Qt 开发跨平台 UI.但是编剧呢? 在这篇博文中,我们将说明如何使用PySide使用IDAPython为 ...
- jenkins报错The goal you specified requires a project to execute but there is no POM inthis directory
报错截图及详细: 15:30:29[ERROR]The goal you specified requires a project to execute but there is no POM i ...