5.30 NOI 模拟
$5.30\ NOI $模拟
高三大哥最后一次模拟考了,祝他们好运
\(T1\)装箱游戏
显然可以将四种字母之间的空缺当做状态枚举
那么这道题就很显然了
#include<bits/stdc++.h>
#define MAXN 305
using namespace std;
int n;
double f[4][MAXN][MAXN][MAXN],a,b,c,d;
bool fl[4][MAXN][MAXN][MAXN];
double dp(int op,int x,int y,int z)
{
if(x<0||y<0||z<0) return 0;
if(x==0&&y==0&&z==0) return 1;
if(fl[op][x][y][z]!=0) return f[op][x][y][z];
fl[op][x][y][z]=1;
//op记录的是目前是第几种转移的
//op==0 只有AD
//op==1 ABD
//op==2 ACD
//op==3 ABCD
//我们把x,y,z分别表示第几个空缺会比较好
if(op==0)
{
double s1=dp(op,x-1,y,z);
double s2=0,s3=0,s4;
for(int i=0;i<x;i++)
{
s2=max(s2,dp(1,i,x-i-1,0));
s3=max(s3,dp(2,i,x-i-1,0));
}
s4=dp(op,x-1,y,z);
f[op][x][y][z]=s1*a+s2*b+s3*c+s4*d;
}
else if(op==1)
{
double s1=dp(op,x-1,y,z);
double s2=max(dp(op,x-1,y,z),dp(op,x,y-1,z));
double s3=0;
double s4=dp(op,x,y-1,z);
for(int i=1;i<=y;i++)
{
s3=max(s3,dp(3,x,y-i,i-1));
}
f[op][x][y][z]=s1*a+s2*b+s3*c+s4*d;
}
else if(op==2)
{
double s1=dp(op,x-1,y,z);
double s2=0;
double s3=max(dp(op,x-1,y,z),dp(op,x,y-1,z));
double s4=dp(op,x,y-1,z);
for(int i=1;i<=x;i++)
{
s2=max(s2,dp(3,i-1,x-i,y));
}
f[op][x][y][z]=s1*a+s2*b+s3*c+s4*d;
}
else
{
double s1=dp(op,x-1,y,z);
double s2=max(dp(op,x-1,y,z),dp(op,x,y-1,z));
double s3=max(dp(op,x,y-1,z),dp(op,x,y,z-1));
double s4=dp(op,x,y,z-1);
f[op][x][y][z]=s1*a+s2*b+s3*c+s4*d;
}
return f[op][x][y][z];
}
int main()
{
scanf("%lld%lf%lf%lf%lf",&n,&a,&b,&c,&d);
a/=100.0;b/=100.0;c/=100.0;d/=100.0;
printf("%.6f\n",dp(0,n,0,0));
}
\(T2\)库图鲁
考场上猜到了结论,最后的策略必然是走一段路然后到了一个终点停止,证明比较显然
然后暴力可以枚举最终点然后模拟,可获得\(30pts\)
发现不虑中间移动的过程,如果这个\(monster\)可以达到最终点,那么就需要统计贡献,否则不需要
证明的话:考虑相遇的充要条件,同一时刻位于同一点,我们既然保证了相遇,那么我们就可以同步移动到终点,那么相遇问题可以转化为到达问题
问题成功转化为,树上其他点到树上一个点的贡献和,然后可以使用点分治
首先\(u\neq v,val_{v\rightarrow u}=a_v(\lfloor\frac{h-max(d,1)}{k}\rfloor+1)\)
就是考虑有多少个完整的轮数可以到达,\(h\)是总时间,减去距离证明在这一段时间可以到,然后判断有多少个起点即可
比较套路的,考虑\(d_{u\rightarrow v}=dep_u+dep_c-2\times dep_{lca}\)
假设\(lca_{u,v}=rt,rt\)为当前分治位于的根
\(val_{v\rightarrow u}=a_v(\lfloor\frac{h-(dep_u+dep_v-2\times lca)}{k}\rfloor+1)\)
\(val_{v\rightarrow u}=a_v(\lfloor\frac{h-(dep_u+dep_v)}{k}-\frac{2\times dep_{lca}}{k}\rfloor+1),dep_{lca}=0 ...\)
\(val_{v\rightarrow u}=a_v(\lfloor\frac{h-(dep_u+dep_v)}{k}\rfloor+1)\)
然后发现这个向下取整很寄
然后继续拆
\(val_{v\rightarrow u}=a_v(\lfloor\frac{(h-dep_u)-dep_v}{k}\rfloor+1)\)
考虑我们这个东西,维护一下模数相等的部分乘一下就好了
我们需要先把子树内的删掉,然后计算外面的贡献,很神仙
然后贡献的话,可以考虑全部插入一个线段树里面,然后最后查询一遍即可
#include<bits/stdc++.h>
#define int long long
#define mid ((l+r)>>1)
#define P make_pair
using namespace std;
int n,k,h,q[1000001],val[100001],res=100000000000000000ll;
int ans[1000001];
vector<int>road[1000001];
int vis[1000001],siz[1000001],maxn[1000001],root;
int read(){
int a=0,b=1;
char ch=getchar();
while((ch<'0'||ch>'9')&&(ch!='-')){
ch=getchar();
}
if(ch=='-'){
b=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
a=a*10+ch-'0';
ch=getchar();
}
return a*b;
}
struct tree{
int rt,tr[2000001],son[2000001][2],cnt,num[2000001];
void clear()
{
for(int i=1;i<=cnt;++i) tr[i]=son[i][0]=son[i][1]=num[i]=0;
cnt=rt=0;
return ;
}
void add(int &x,int l,int r,int p,int v)
{
if(r<p||p<l) return ;
if(!x) x=++cnt;
num[x]+=v,tr[x]+=p*v;
if(l==r) return;
add(son[x][0],l,mid,p,v);
add(son[x][1],mid+1,r,p,v);
}
int query(int x,int l,int r,int v)
{
if(l>v) return num[x]*(v+k)-tr[x];
if(r<=v) return num[x]*v-tr[x];
return query(son[x][0],l,mid,v)+query(son[x][1],mid+1,r,v);
}
}T;
void get_root(int x,int f,int alls)
{
siz[x]=1; maxn[x]=0;
for(int i=0;i<road[x].size();++i)
{
if(road[x][i]==f||vis[road[x][i]]) continue;
get_root(road[x][i],x,alls);
maxn[x]=max(maxn[x],siz[road[x][i]]);
siz[x]+=siz[road[x][i]];
}
maxn[x]=max(maxn[x],alls-siz[x]);
if(maxn[x]<=maxn[root]) root=x;
}
int poi[1000001],lons[1000001],son[1000001],cnt;
pair<int,int> ques[1000001];
void find_roads(int x,int f,int v,int sy)
{
++cnt;
poi[cnt]=x;lons[x]=v;//深度
ques[cnt]=P(h-lons[x],x);//我们这个询问要询问
//维护式子的前一半,(h-dep[x])-dep[y]
for(int i=0;i<road[x].size();++i)
{
if(road[x][i]==f||vis[road[x][i]]) continue;
find_roads(road[x][i],x,v+1,sy);
}
}
bool comp(int a,int b)
{
return lons[a]<lons[b];
}
void get_ans(int x)
{
cnt=0;
poi[++cnt]=x;
//把能到的点全部扫一遍
//我们目前统计的都是跨过根的贡献
lons[x]=0;//dep
ques[cnt]=P(h-lons[x],x);
//询问
for(int i=0;i<road[x].size();++i)
{
if(!vis[road[x][i]])
{
int lst=cnt;
//找到这个子树的范围
find_roads(road[x][i],x,1,road[x][i]);
sort(poi+lst+1,poi+cnt+1,comp);
sort(ques+lst+1,ques+cnt+1);
T.clear();
int posr=lst+1,posl=lst+1,sum=0,valsum=0;
for(int j=lst+1;j<=cnt;++j)
{
int q=ques[j].first;
if(q<0) continue;
while(posr<=cnt&&lons[poi[posr]]<=q)
{
T.add(T.rt,0,k,lons[poi[posr]]%k,val[poi[posr]]);
sum+=-lons[poi[posr]]*val[poi[posr]];
valsum+=val[poi[posr]];
++posr;
}
ans[ques[j].second]-=((q*valsum+sum-T.query(T.rt,0,k,q%k))/k+valsum);
}
}
}
T.clear();
sort(poi+1,poi+1+cnt,comp);
sort(ques+1,ques+cnt+1);
int posr=1,posl=1,sum=0,valsum=0;
for(int j=1;j<=cnt;++j)
{
int q=ques[j].first;
if(q<0) continue;
while(posr<=cnt&&lons[poi[posr]]<=q)
{
T.add(T.rt,0,k,lons[poi[posr]]%k,val[poi[posr]]);
sum+=-lons[poi[posr]]*val[poi[posr]];
valsum+=val[poi[posr]];
++posr;
}
ans[ques[j].second]+=((q*valsum+sum-T.query(T.rt,0,k,q%k))/k+valsum);
}
}
void solve(int x)
{
vis[x]=true;
get_ans(x);
for(int i=0;i<road[x].size();++i)
{
if(!vis[road[x][i]])
{
root=0;
get_root(road[x][i],x,siz[road[x][i]]);
solve(root);
}
}
}
void dfs_ans(int x,int f,int v)
{
if(v>h) return ;
for(int i=0;i<road[x].size();++i) if(road[x][i]!=f)dfs_ans(road[x][i],x,v+1);
if(h%k==0) ans[x]-=val[x];
res=min(res,ans[x]);
}
signed main()
{
maxn[0]=1000000;
n=read(),k=read(),h=read();
for(int i=1;i<=n;++i) val[i]=read();
for(int i=1,u,v,w;i<n;++i)
{
u=read(),v=read();
road[u].push_back(v);
road[v].push_back(u);
}
get_root(1,0,n);//easily
solve(root);
dfs_ans(1,1,0);
cout<<res;
}
\(T3\)树
前两问随便线段树维护一下就好了
第三个操作基于一个贪心
我们要求区间的连续两个数绝对值不超过\(k\)
我们要对于点\(i\)
\(a_i+k>=a_{i+1},a_i+k>=a_{i-1}\)
我们对于每个条件从一侧往另一侧扫一遍贪心更改即可,复杂度\(O(nm)\)
考虑优化这个过程
考虑维护差分数组,我们第二个操作最多只会增加两个需改变的点,但每次三操作会减少,我们这个东西有势能保护
我们三操作最后变成了区间赋等差数列即可,范围可以使用二分轻松解决
5.30 NOI 模拟的更多相关文章
- 5.23 NOI 模拟
$5.23\ NOI $模拟 \(T1\)简单的计算几何题 \(zjr:\)我当时没改,那么自己看题解吧 倒是有个简单的随机化方法(能获得\(72pts,\)正确性未知)\(:\) 随机两条切椭圆的平 ...
- 5.6 NOI模拟
\(5.6\ NOI\)模拟 明天就母亲节了,给家里打了个电话(\(lj\ hsez\)断我电话的电,在宿舍打不了,只能用教练手机打了) 其实我不是很能看到自己的\(future,\)甚至看不到高三的 ...
- 5.4 NOI模拟
\(5.4\ NOI\)模拟 \(T1\) 想到分讨,但是暴力输出一下方案之后有很多特别的情况要讨论,就弃了... 假设\(a\)是原序列,\(b\)是我们得到的序列 设\(i\)是最长公共前缀,\( ...
- @NOI模拟2017.06.30 - T3@ Right
目录 @description@ @solution@ @part - 1@ @part - 2@ @accepted code@ @details@ @description@ JOHNKRAM 和 ...
- @NOI模拟2017.06.30 - T1@ Left
目录 @description@ @solution@ @accepted code@ @details@ @description@ JOHNKRAM 最近在研究排序网络,但他发现他不会制作比较器, ...
- 6.28 NOI模拟赛 好题 状压dp 随机化
算是一道比较新颖的题目 尽管好像是两年前的省选模拟赛题目.. 对于20%的分数 可以进行爆搜,对于另外20%的数据 因为k很小所以考虑上状压dp. 观察最后答案是一个连通块 从而可以发现这个连通块必然 ...
- 2016.10.30 NOIP模拟赛 day2 PM 整理
满分:300分 直接全部爆零,真的是很坑啊! 10.30的题目+数据:链接:http://pan.baidu.com/s/1jHXLace 密码:i784 T1: 题目中的难点就是每次折叠的点可能应经 ...
- 2016.10.30 NOIP模拟赛 day2 AM 整理
题目+数据:链接:http://pan.baidu.com/s/1gfBg4h1 密码:ho7o 总共得了:130分, 1:100分 2:30分(只会这30分的暴力) 3:0(毫无思路) 虽然不高, ...
- NOI模拟赛 Day1
[考完试不想说话系列] 他们都会做呢QAQ 我毛线也不会呢QAQ 悲伤ING 考试问题: 1.感觉不是很清醒,有点困╯﹏╰ 2.为啥总不按照计划来!!! 3.脑洞在哪里 4.把模拟赛当作真正的比赛,紧 ...
随机推荐
- ElasticSearch7.3学习(二十六)----搜索(Search)参数总结、结果跳跃(bouncing results)问题解析
1.preference 首先引入一个bouncing results问题,两个document排序,field值相同:不同的shard上,可能排序不同:每次请求轮询打到不同的replica shar ...
- 安装Zabbix到Ubuntu(APT)
运行环境 系统版本:Ubuntu 16.04.2 LTS 软件版本:Zabbix-4.0.2 硬件要求:无 安装过程 1.安装APT-Zabbix存储库 APT-Zabbix存储库由Zabbix官网提 ...
- MAC M1安装多个JDK版本及动态切换
JDK版本下载 下载地址:https://www.azul.com/downloads/?package=jdk 筛选一下macOS的ARM 64-bit架构的JDK版本,下载对应版本即可.最好直接下 ...
- 关于『HTML5』第一弹
关于『HTML5』:第一弹 建议缩放90%食用 祝各位国庆节快乐!!1 经过了「过时的 HTML」.「正当时的 Markdown」的双重洗礼后,我下定决心,好好学习HTML5 这回不过时了吧(其实和 ...
- 《Mybatis 手撸专栏》第10章:使用策略模式,调用参数处理器
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 你这代码写的,咋这么轴呢! 说到轴,让我想起初中上学时老师说的话:"你那脑 ...
- 如何用HMS Core位置和地图服务实现附近地点路径规划功能
日常出行中,路径规划是很重要的部分.用户想要去往某个地点,获取到该地点的所有路径,再根据预估出行时间自行选择合适的路线,极大方便出行.平时生活中也存在大量使用场景,在出行类App中,根据乘客的目的地可 ...
- 【zigbee无线通信模块步步详解】ZigBee3.0模块建立远程网络控制方法
本文以路灯控制应用为例,简述ZigBee3.0模块使用流程. 一.建立网络 1.通过USB转串口模块将出厂的ZigBee自组网模块连接,打开上位机软件"E180-ZG120A-Setting ...
- VMware 虚拟机安装CentOS镜像详细步骤
CentOS目前官网提供的下载版本有6.7.8,最新的版本为8,不过个人推荐CentOS 7 的版本,因为相比较于最新版本,版本7更加地稳定.而相比于版本6,版本7新增了很多的功能.CentOS 7 ...
- 几种常见的DoS攻击
DoS为Denial of Service的简称,意思是拒绝服务.DoS攻击是一种使被攻击者无法正常提供服务的攻击.常见的攻击方式有以下几种类型: LAND Local Area Network ...
- 毕业论文着急了?Python疫情数据分析,并做数据可视化展示
采集流程 一..明确需求 采集/确诊人数/新增人数 二.代码流程 四大步骤 发送请求 获取数据 网页源代码 解析数据 筛选一些我想用的数据 保存数据 保存成表格 做数据可视化分析 开始代码 1. 发送 ...