10/6 牛客 2022 tg 第一场
难度???
A
细节巨多卡爆常数的二分答案,pass
B
二进制贡献考虑枚举位数,对于一个点,只有他自己和直接儿子可以有贡献, 统计第 位上 的个数 ,只有为奇数时有贡献 ,这样的方案数为 =。同时还要考虑其他不相关结点的移动,以及该点上只有一个点(无贡献)的情况,细节一堆。
C
考虑贪心构造,显然我们尽量让 多次交换,把剩下的 尽量连续放在一起,
枚举 交换了多少次,形如 BBB...BA BBB...BA
考虑填上剩下的 :一个放在开头可以多 权值,剩下的在串里的每个 后面接上 个可获得 的权值。
考虑填上剩下的 :一个放在末尾可以多 权值,剩下的填充进串里每凑足 个 可获得 的权值。
D
《容易看出》这是一个分段函数,形如
我们的目标是维护这个分段函数的两个断点 和 。
(转载)
于是可以用线段树维护断点。
先考虑单个操作, 表示操作 的分段函数,有
再考虑如何合并,
若 后面跟着 (避免歧义,将 中的 表示成 ),则
即
这里根据加上的值,断点位置会改变。跟着 同理。
若 后面跟着 ,则
即直接加 就行了, 同理。
若 后面跟着 (将 中的 表示成 ),则
事实上所谓的 和 ,它们的区别只是对初始值限制的范围不同,可以看作同一类型的函数。
综合以上,需要记录的有:断点 和 ,需要加的数 ,可以写出以下维护代码:
#define ls p<<1
#define rs p<<1|1
struct node{ll sum,L,R;}tre[N<<2];
void pushup(int p){//左边合并到右边就是把左边的范围丢到右边限制一下
tre[p].L=max(min(tre[ls].L,tre[rs].R-tre[ls].sum),tre[rs].L-tre[ls].sum);
tre[p].R=max(min(tre[ls].R,tre[rs].R-tre[ls].sum),tre[rs].L-tre[ls].sum);
tre[p].sum=tre[ls].sum+tre[rs].sum;
}
void modify(int p,int l,int r,int pos,int op,ll val){
if(l==r){//限制范围
if(op==1)tre[p]=(node){val,-inf,inf};
if(op==2)tre[p]=(node){0,-inf,val};
if(op==3)tre[p]=(node){0,val,inf};
return;
}
int mid=l+r>>1;
if(pos<=mid)modify(ls,l,mid,pos,op,val);
else modify(rs,mid+1,r,pos,op,val);
pushup(p);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】