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小时太少,我的题目很良心,都很简单. 答案可以在模拟测试 ...
随机推荐
- 解决SpringMVC重复提交的问题
方法一:通过重定向采取请求转发的方式完成表单内容的添加会造成内容的重复插入.当向Servlet发送一条增加记录的请求后,servlet首先向数据库增加一条记录,然后又从数据库中查询出所有数据,接着转发 ...
- 01-Tkinter教程-窗口的管理与设置
Tkinter介绍 官方用的GUI工具包--Tkinter(IDLE就是用这个开发的). Tkinter是Python的标准GUI库,它实际是建立在Tk技术上的.在大多数Unix平台以及Windows ...
- 根据所处位置提取单元格内容的函数(left、right、mid)和查找字符串位于单元格内容第几位的函数(find)
1.从左到右提取:left(value,num_chars) 注释:value为操纵单元格,num_chars表示截取的字符的数量 2.从右往左提取:right(value,num_chars) 注释 ...
- C#调用JAVA(一)制作jar包
1 //AndroidJavaClass类可以理解为某一个类 2 //AndroidJavaObject类可以理解为某一个类中的一个对象 打开AS,创建一个空项目 输入项目名,包名,本地路径以及语言之 ...
- 27、myslq更改为不自动提交
27.1.说明: 默认情况下, MySQL启用自动提交模式(变量autocommit为ON).这意味着, 只要你执行DML操作的语句, MySQL会立即隐式提交事务(Implicit Commit). ...
- keycloak文章汇总
keycloak文章汇总 Keycloak是一个致力于解决应用和服务身份验证与访问管理的开源工具.可以通过简单的配置达到保护应用和服务的目的. 用户管理 你的应用不需要开发登录模块,验证用户和保存用户 ...
- 浅读tomcat架构设计之Pipeline-Valve管道(4)
tomcat Container容器处理请求是使用Pipeline-Valve管道来处理的,后续写的tomcat内存马,和他紧密结合 Pipeline-Valve是责任链模式,责任链模式是指在一个请求 ...
- 《汇编语言程序设计》(Professional Assembly Language)学习笔记(二)
挖坑:学习笔记(一)讲述如何在 Windows Vmware 上安装 Ubuntu 20.04 实践环境 本文是基于Ubuntu 20.04平台进行实验,下文中的解决方法都基于此前提 问题记录 问题一 ...
- java设计模式(9):模板方法模式(TemplateMethod)
一,定义:模板方法模式定义了一个操作中的算法骨架,而将一些步骤延迟到子类中.模板方法使得子类可以不改变一个算法的结构即可重定义该算法的某些特定步骤. 二,类图: 三,通过小例子讲解: 这个模式一般用在 ...
- 【知识点】H264, H265硬件编解码基础及码流分析
前言 音视频开发需要你懂得音视频中一些基本概念,针对编解码而言,我们必须提前懂得编解码器的一些特性,码流的结构,码流中一些重要信息如sps,pps,vps,start code以及基本的工作原理,而大 ...