OI 笑传 #21

news/2025/10/21 23:38:42/文章来源:https://www.cnblogs.com/hm2nsite/p/19156686

ワールドエンドガールフレンド

今天是周天 VP 的洛谷的 S 模拟。

结果起晚了。。。十点才开题。打了 3h。

结果是 \(100+100+0+0=200\),T3 暴力没打,T4 啥也不会。大样例挺牛的,都过了就不会挂分,给好评。

下面是赛时。

T1

清新小思维,想了一会知道了后缀选一定是不劣的,于是考虑从后面往前加数,怎么维护前缀和数组中 \(0\) 的个数。

我做这个用了个比较猎奇的东西就是初始时维护一个指针 \(p\) 指向 \(0\),从后往前加数,假设加 \(a_i\),那么就把指针现在指的位置 \(+1\),之后把指针移到 \(p-a_i\) 那个地方,每次移动之后统计移动到的位置的最大值就是答案。

相当于是一个移动参考系的过程,\(p\) 指向的就是原点的位置。

我觉得挺有道理的,想完写完并过了所有大样例用了 20min。

实现用 map 即可。

code

Show me the code
#define rd read()
#define mkp make_pair
#define ls p<<1
#define rs p<<1|1
#define rep(i,a,b) for( int i=(a); i<=(b); ++i)
#define per(i,a,b) for( int i=(a); i>=(b); --i)
#include<bits/stdc++.h>
using namespace std;
typedef long long i64;
typedef unsigned long long u64;
typedef unsigned int u32;
typedef __int128 i128;
i64 read(){i64 x=0,f=1;char c=getchar();while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar();}while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}return x*f;
}
const int N=1e6+5;
map<i64,int> cnt;
int arr[N];
void init(){cnt.clear();return ;}
void solve(){int n;cin>>n;for(int i=1;i<=n;i++){arr[i]=rd;}i64 p=0;int ans=0;for(int i=n;i>=1;i--){cnt[p]++;p-=arr[i];if(cnt.find(p)==cnt.end())cnt[p]=0;ans=max(ans,cnt[p]);}cout<<ans<<'\n';
}
int main(){int T;cin>>T;while(T--){init();solve();}return 0;
}

T2.1

又是这么一坨题面糊我脸上,想起来去年超速检测。

观察了一下猜又是个性质计数题,于是先去开了 T3。

T3.1

事数据结构,这东西骗分好说啊,于是先回去看 T2 了。

T4 事博弈+计数,这东西在 T4 就不是什么好东西。

T2

部分分似乎很少。只能去看性质了。

在家里 walkaround 了一会发现选出来的点必须同高。

然后选出来的那些子树我们只关心它的最大深度,这个是显然的,因为树高肯定得连续的。

但是这个大树似乎很烦,我再想想。

然后又出了个实际错误的结论是我们选出来的第一棵子树必须是深度最小的那一棵。

于是好像把每种深度的点及其引出来的子树按照高度统计一下,对于每种高度分别计数,再加起来就做完了?

再想想式子,为了不重复,我们每次都指定一个点作为 \(1\) 位置的点,这样计数一定是好的,不重复,而且由于引出子树的深度相同的点是等价的,计数完之后乘个数量就行了。

考虑现在钦定了一个点,设深度最小的点的数量有 \(cnt_1\) 个,于是枚举从剩下的 \(cnt_1-1\) 个点里面选出来了 \(i\) 个点,当然是必须要选的,所以 \(i\in[1,\min(cnt_1-1,k-1)]\) 这个好说。

再设其它点有 \(cnt_2\) 个,显然 \(cnt_1+cnt_2\) 就是深度为这个的点的数量,然后式子就是:

\[res=\sum_{i=1}^{\min(cnt_1-1,k-1)} \binom{i}{cnt_1-1} \times \binom{k-i-1}{cnt_2} \]

之后累加进答案就是:

\[ans\leftarrow ans+res\times (k-1)! \times cnt_1 \]

注意时刻取模。

做完了??

哦想想从什么深度才能开始计数,显然最深的就是可以的。

哦还有这个 \(cnt_1 \ge 2\),不然罩不住选出来的第一个。

嗯,写写看。

code 1

Show me the code
#define rd read()
#define mkp make_pair
#define ls p<<1
#define rs p<<1|1
#define rep(i,a,b) for( int i=(a); i<=(b); ++i)
#define per(i,a,b) for( int i=(a); i>=(b); --i)
#include<bits/stdc++.h>
using namespace std;
typedef long long i64;
typedef unsigned long long u64;
typedef unsigned int u32;
typedef __int128 i128;
i64 read(){i64 x=0,f=1;char c=getchar();while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar();}while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}return x*f;
}
const int N=1e6+100;
const int mod=998244353;
vector<int> e[N];
vector<int> lv[N];
int dep[N];int mdep[N];
i64 fac[N];
i64 x,y;
i64 ksm(i64 a,i64 b){i64 res=1,k=a;while(b){if(b&1){res=res*k%mod;}k=k*k%mod;b>>=1;}return res;
}
i64 inv(i64 c){return ksm(c,mod-2);
}
i64 C(i64 n,i64 m){return fac[n]*inv(fac[m]*fac[n-m]%mod)%mod;
}
int beg=0x3f3f3f3f;
void dfs(int u,int fa){bool leaf=1;for(int v:e[u]){if(v==fa)continue;mdep[v]=dep[v]=dep[u]+1;leaf=0;dfs(v,u);mdep[u]=max(mdep[u],mdep[v]);}lv[dep[u]].push_back(mdep[u]);if(leaf)beg=min(beg,dep[u]);return ;
}
int main(){fac[0]=1;for(int i=1;i<=1e6+3;i++)fac[i]=fac[i-1]*i%mod;int n;int k;cin>>n>>k;for(int i=1;i<n;i++){int v;cin>>v;e[i+1].push_back(v);e[v].push_back(i+1);}mdep[1]=dep[1]=1;dfs(1,0);i64 ans=0;for(int i=beg;i>=2;i--){if(lv[i].size()<=k)continue;sort(lv[i].begin(),lv[i].end());cout<<ans<<'\n';int cnt1=0,cnt2=0;int mi=lv[i][0];for(int v:lv[i]){if(v==mi)cnt1++;else break;}    if(cnt1<=1)continue;cnt2=lv[i].size()-cnt1;i64 res=0;for(int i=1;i<=min(cnt1-1,k-1);i++){res=(res+C(cnt1-1,i)*C(cnt2,k-i-1)%mod)%mod;}ans=(ans+res*fac[k-1]%mod*cnt1%mod)%mod;cout<<ans<<'\n';}cout<<ans;return 0;
}

一遍写对了,但是过不了第三个样例。

手摸一下发现是让大树挂这相同高度的树,断开其它所有深度比它大的情况。

这个统计也好办啊,判断一下就行。

于是改了改:

code 2

Show me the code
#define rd read()
#define mkp make_pair
#define ls p<<1
#define rs p<<1|1
#define rep(i,a,b) for( int i=(a); i<=(b); ++i)
#define per(i,a,b) for( int i=(a); i>=(b); --i)
#include<bits/stdc++.h>
using namespace std;
typedef long long i64;
typedef unsigned long long u64;
typedef unsigned int u32;
typedef __int128 i128;
i64 read(){i64 x=0,f=1;char c=getchar();while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar();}while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}return x*f;
}
const int N=1e6+100;
const int mod=998244353;
vector<int> e[N];
vector<int> lv[N];
int dep[N];int mdep[N];
i64 fac[N];
i64 x,y;
i64 ksm(i64 a,i64 b){i64 res=1,k=a;while(b){if(b&1){res=res*k%mod;}k=k*k%mod;b>>=1;}return res;
}
i64 inv(i64 c){return ksm(c,mod-2);
}
i64 C(i64 n,i64 m){return fac[n]*inv(fac[m]*fac[n-m]%mod)%mod;
}
int beg=0x3f3f3f3f;
void dfs(int u,int fa){bool leaf=1;for(int v:e[u]){if(v==fa)continue;mdep[v]=dep[v]=dep[u]+1;leaf=0;dfs(v,u);mdep[u]=max(mdep[u],mdep[v]);}lv[dep[u]].push_back(mdep[u]);if(leaf)beg=min(beg,dep[u]);return ;
}
int main(){fac[0]=1;for(int i=1;i<=1e6+3;i++)fac[i]=fac[i-1]*i%mod;int n;int k;cin>>n>>k;for(int i=1;i<n;i++){int v;cin>>v;e[i+1].push_back(v);e[v].push_back(i+1);}mdep[1]=dep[1]=1;dfs(1,0);i64 ans=0;for(int i=beg;i>=2;i--){if(lv[i].size()<=k)continue;sort(lv[i].begin(),lv[i].end());cout<<ans<<'\n';int cnt1=0,cnt2=0;int mi=lv[i][0];for(int v:lv[i]){if(v==mi)cnt1++;else break;}    if(cnt1<=1)continue;cnt2=lv[i].size()-cnt1;i64 res=0;if(cnt2==k-1)res=1;for(int i=1;i<=min(cnt1-1,k-1);i++){res=(res+C(cnt1-1,i)*C(cnt2,k-i-1)%mod)%mod;}ans=(ans+res*fac[k-1]%mod*cnt1%mod)%mod;cout<<ans<<'\n';}cout<<ans;return 0;
}

现在样例都过了,此时已经过去 1h20min。

满心欢喜去测大样例,结果只过了满二叉树的 case。

我。。。。这还有啥情况啊。

于是只能写对拍了,写个 \(k=2\) 的就行了,因为大样例就是这个。

写完拍上又是 10min。。。

最后还真拍出来了,就是可以选任意深度的点,只要保证大树和其它树能交出来选的深度就行。

具体我在草纸上分了三种情况,就是选的深度最小的,中间的,最大的,三种情况。

然后每种情况钦定一个点做 \(1\) 号树,考虑选不选和自己相同深度的点的情况。

这里式子和上面其实挺像的,唯一不同的就是选最大深度树的时候。这时候 \(k\) 个点必须选的全是最大深度树,断深度小的一定是不行的。

于是式子就是:

\[\binom{k-1}{cnt_1-1} \times (k-1)! \times cnt_1 \]

这下应该对了,细细实现了一下就过了所有大样例。

赛后知道这东西评了蓝,我??这 DP 都不用应该到不了蓝吧。

写完+调完之后过去了 2h10min。

code

Show me the code
#define rd read()
#define mkp make_pair
#define ls p<<1
#define rs p<<1|1
#define rep(i,a,b) for( int i=(a); i<=(b); ++i)
#define per(i,a,b) for( int i=(a); i>=(b); --i)
#include<bits/stdc++.h>
using namespace std;
typedef long long i64;
typedef unsigned long long u64;
typedef unsigned int u32;
typedef __int128 i128;
i64 read(){i64 x=0,f=1;char c=getchar();while(c>'9'||c<'0'){if(c=='-') f=-1;c=getchar();}while(c>='0'&&c<='9'){x=(x<<3)+(x<<1)+(c^48);c=getchar();}return x*f;
}
const int N=1e6+100;
const int mod=998244353;
vector<int> e[N];
vector<int> lv[N];
int dep[N];int mdep[N];
i64 fac[N];
i64 x,y;
i64 ksm(i64 a,i64 b){i64 res=1,k=a;while(b){if(b&1){res=res*k%mod;}k=k*k%mod;b>>=1;}return res;
}
i64 inv(i64 c){return ksm(c,mod-2);
}
i64 C(i64 n,i64 m){if(n<m)return 0;return fac[n]*inv(fac[m]*fac[n-m]%mod)%mod;
}
int beg=0;
void dfs(int u,int fa){bool leaf=1;for(int v:e[u]){if(v==fa)continue;mdep[v]=dep[v]=dep[u]+1;leaf=0;dfs(v,u);mdep[u]=max(mdep[u],mdep[v]);}lv[dep[u]].push_back(mdep[u]);if(leaf)beg=max(beg,dep[u]);return ;
}
int main(){fac[0]=1;for(int i=1;i<=1e6+3;i++)fac[i]=fac[i-1]*i%mod;int n;int k;cin>>n>>k;for(int i=1;i<n;i++){int v;v=rd;e[i+1].push_back(v);e[v].push_back(i+1);}mdep[1]=dep[1]=1;dfs(1,0);i64 ans=0;for(int i=beg;i>=2;i--){if(lv[i].size()<=k)continue;sort(lv[i].begin(),lv[i].end());int cnt1=0,cnt2=0,cnt3=0;int mi=lv[i][0];for(int j=0;j<lv[i].size();j++){cnt1+=cnt2;cnt2=0;// cout<<cnt1<<' '<<cnt2<<' '<<cnt3<<'\n';while(j<lv[i].size()&&lv[i][j]==mi)cnt2++,j++;if(j<lv[i].size())mi=lv[i][j];j--;cnt3=lv[i].size()-cnt1-cnt2;if(cnt2<=1)continue;int res=0;if(cnt1==0){if(cnt3==k-1)res=1;for(int i=1;i<=min(cnt2-1,k-1);i++){res=(res+C(cnt2-1,i)*C(cnt3,k-i-1)%mod)%mod;}ans=(ans+res*fac[k-1]%mod*cnt2%mod)%mod;}else if(cnt3==0){if(cnt2<=k)continue;ans=(ans+C(cnt2-1,k-1)%mod*fac[k-1]%mod*cnt2%mod)%mod;}else{if(cnt3+cnt2<=k)continue;if(cnt3==k-1)res=1;for(int i=1;i<=min(cnt2-1,k-1);i++){res=(res+C(cnt2-1,i)*C(cnt3,k-i-1)%mod)%mod;}ans=(ans+res*fac[k-1]%mod*cnt2%mod)%mod;}}    }cout<<ans;return 0;
}

T3

首先否了一个无脑区间覆盖的贪心做法。

然后想到了可以记录下每个点被停止服务的右端点在哪里。

这个东西可以区间覆盖做。

然后好像这个停止服务的位置是有单调性的!

于是考虑询问 \(l,r\) 车站,我们一定可以在 \(l\) 找到一个位置 \(k\),使得 \(k\) 不能服务到 \(r\),但 \(k-1\) 可以,这个线段树二分做是好说的。

于是 \(k\sim l\) 的答案就是自己停止服务右端点加一位置的车站和自己的距离差。\(1\sim k-1\) 的答案就是自己到 \(r\) 的距离差。

前面那一段当然取 \(k-1\) 是最优的,后面呢?

又想了想发现我们只关心后面这段的最小值。

但是你最小值就要在区间覆盖的时候维护一遍了。。。

但是好像这种做法能过掉 60pts 的部分分?我觉得已经够牛了。

但是还没实现代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/942776.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

[Tool] lsof: 列出打开的文件描述符

[Tool] lsof: 列出打开的文件描述符$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");目录1. 概述2. 前提条件3. 常用选项和用法4. 常用示例4.1 查看指定进程…

Day1文本格式化标签

用来为文本添加特殊格式,突出重点,常见的文本格式有:加粗,下划线,倾斜,删除线等在实际应用中,一般都是使用左边的标签,因为其在语义上自带强调含义 <!DOCTYPE html> <html lang="en"> &l…

24信计2班 17曾向嵩 pytorch66页实验题

import torch from torch import optim, nn from torchvision import datasets, transforms from torch.utils.data import DataLoader import torch.nn.functional as Fdevice = torch.device(cuda if torch.cuda.is_…

解答这些常见的智能合约安全问题,并提供相应的防护措施

我来详细解答这些常见的智能合约安全问题,并提供相应的防护措施: 1. 重入攻击 (Reentrancy Attack) 攻击原理 重入攻击是指恶意合约在接收以太币后,立即回调发送方合约,导致状态不一致。 攻击示例 // 易受攻击的合…

读AI赋能05消费者盈余

读AI赋能05消费者盈余1. 肖莎娜朱布夫 1.1. Shoshana Zuboff 1.2. 哈佛商学院荣誉退休教授 1.3. 《监控资本主义》1.3.1. 2019年最佳图书之1.3.2. 谷歌和Facebook等公司用一种“感知化、网络化、计算化的基础设施”取代…

解答这些 Solidity 开发中的重要问题

我来详细解答这些 Solidity 开发中的重要问题: 1. Calldata 的含义和使用场景 Calldata 定义 calldata 是函数参数的存储位置,专门用于存储外部函数调用的参数数据。 使用场景 contract CalldataExample {// 1. 外部…

Day1排版标签,标题与段落

标题标签一般在新闻标题,文章标题等内容上使用,且是双标签,标签名为h1~h6,而h1标签在一个网页中只能用一次,一般用来放新闻标题或网页logo,其余标题标签则无次数限制、 各级标题标签的字号都会加粗,等级越大,字…

梦回大唐王一牛

梦回大唐王一牛英雄不装车. 爱国者,坦克都贴边建.要塞满医疗车.

grpc 哼哈二将,你值得拥有

kong网关转发http服务,各大博主都已经聊包浆了。 kong网关原生支持代理gRPC请求,本文通过一个示例来记录通过kong网关管理gRPC服务,并且使用grpcbin和grpcurl哼哈二将来模拟和验证grpc服务能力。kong网关核心的控制…

一文读懂字体文件

一文读懂字体文件这篇文章是从0到1自定义富文本渲染的原理篇之一,此外你还可能感兴趣: 更多内容欢迎关注公众号:非专业程序员Ping一文读懂字符与编码 一文读懂字符、字形、字体 一文读懂字体文件 从0到1自定义文字排…

解释这些 Solidity 智能合约的核心概念

我来详细解释这些 Solidity 智能合约的核心概念: 1. 合约生命周期 合约部署阶段 // 1. 合约创建 contract MyContract {// 2. 状态变量初始化uint256 public value;address public owner;// 3. 构造函数执行construct…

你的项目一团糟-不是你的错-是框架的锅

GitHub 主页 你的项目一团糟?不是你的错,是框架的“锅”!📂➡️🏛️ 每个程序员都经历过那个瞬间。你加入一个新项目,或者时隔半年重新打开一个自己写的项目,然后,你感到了那种熟悉的、令人窒息的混乱。🌪…

别再猜了-开始测量吧-一份实用的Web性能指南

GitHub 主页 别再猜了,开始测量吧:一份实用的 Web 性能指南 又是一年“黑五”,凌晨三点,我的手机像疯了一样尖叫起来。😱 不是闹钟,是监控警报。我们的主打电商服务,那个我们花了半年心血构建的系统,在流量洪…

你的错误处理一团糟-是时候修复它了-️

GitHub 主页 你的错误处理一团糟,是时候修复它了!🛠️ 我还记得那个让我彻夜难眠的 bug。一个支付回调接口,在处理一个罕见的、来自第三方支付网关的异常状态码时,一个Promise链中的.catch()被无意中遗漏了。结果…

[网络] [iproute2] tc: Linux 带宽限制(Token Bucket Filter 和 HTB)使用指南

[网络] [iproute2] tc: Linux 带宽限制(Token Bucket Filter 和 HTB)使用指南$(".postTitle2").removeClass("postTitle2").addClass("singleposttitle");参考:iproute2: 网络管理利…

C++编程练习

// 阿汪面前有两只盲盒,每只盒子打开都有两种可能:或者装了 X 克狗粮,或者是一只容量为 Y 克的狗粮储蓄盒。如果是狗粮,阿汪可以快乐地吃掉;如果是空储蓄盒,那就倒霉了,阿汪必须想办法找到狗粮把这只储蓄盒装满…

newDay14

1.做了几个Java的小练习,背背单词,写了一些英语作业,时间还是不太够 2.明天课就少了,继续往下学 3.自己c++还是太差了,java学得差不多就回去补c++

L07_在RuoYI项目中添加自己的接口并实现CRUD功能(轻松+AI版)

这里是废话部分 从来没有写过如此轻松的作业,上课两个多小时就听进去了几分钟的东西,这几分钟的东西还是操作,其他是半点都没入入脑,靠着这几分钟的东西,轻松的完成了作业的1/2。 在L06中折磨的看了三天的文档,大…

大二to大三暑假大三上前半学期总结

比赛,学习,刚谈上恋爱,可是然后呢?其实心态得到了比较大的改变,比大二下的时候好受了很多,可能是逐渐接收了事实了。 比较大的事情其实也没几个,第一是和同学一起去打了一个超算比赛 是并行应用挑战赛2025,去鄂…