3.22
牛客模拟
by Hehe_0
A :游游的整数反转
题意即反转前k位,字符串翻转,直接获取长度然后反转就行,另:$ reverse $ 字符反转函数:.begin() , .end()
int l=x.size();
for(int i=k-1; i>=0; i--)
cout<<x[i];
for(int i=k; i<l; i++)
cout<<x[i];
B:小蓝的旅游
类比一笔画问题,我们先想象思考能够满足条件的情况然后去推理找规律;因为从左上角出发到左下角,数据范围1e5纯暴力显然不可行,需要进行转化

结论:可行情况为n为偶数时或者n为奇数m也为奇数
C:先交换
显然就3种情况:
- 第一位就是奇数 》》0
- 后面有小的奇数 》》1
- 其他 》》-1
D :Crying 与选秀
挺裸的一个题,平时比赛里面我个人认为堆还是比较实用多见的,这个题写法很多样,时间上用起来也比较充裕。虽然是用set或者pq很裸,但是还是建议大家会手写大根小根堆。
我们每一个元素需要维护的值就是他的id和分数,然后for循环输入数据每一次入堆,超过六个了就弹出来一个,然后判断这个弹出来的是不是我们当前操作这个新元素,如果是就不用管,如果不是我们需要记录这个新的元素顶掉的人的id,可以直接开一个
数组记录。
if(s.size()>6)
{
int u=s.top().id;
s.pop();
if(u!=i)
{
cnt++;
ans[i]=u;
}
else
ans[i]=0;
}
else
{
ans[i]=0;
cnt++;
}
E :茉茉的密码
可能会有人说,啊,这个多串匹配超纲了,就算是哈希完了二分去找也好难写
----》任意一个公共子串 ,是不是把这个关键字眼扣出来应该都懂了吧
构造题 约等于 找规律偷鸡题
直接开桶统计字符出现情况,code略
F :最多数组数量
首先我们显然需要利用前缀和O(1)获取区间和。首先我们可以从最暴力的分段情况开始 1,2-(n-1) , n 然后对于一个确定的i或者j,来看i或者j(另一个)的可行的取值情况是单调的($p_i$>0),所以可以对于一个确定直接二分确定最大的那个i取值,然后j--,进行相同的过程
while(l<=r)
{
if(s1>pre[i]&&s1>s2)
r=mid-1;
else
l=mid+1;
if(s3>pre[i]&&s3>s[n]-s[l])
ans+=n-l;
}
G :游游的二进制树
dfs暴力,每一次延长就是左移一位
void dfs(int x,int fa,int k)
{
if(x!=fa&&k>=l&&k<=r)
sum++;
for(int i=head[x];i;i=nxt[i])
{
int y=to[i];
if(!(y-fa))
continue;
if(((k<<1)+z[y])<=r)
dfs(to,x,(k<<1)+z[y]);
}
return ;
}
H :最短?路径
另附:[[JLOI2011] 飞行路线]([P4568 JLOI2011] 飞行路线 - 洛谷)
第一眼是dp,经过我们转化,发现在经过一部分的路径的‘不休息’相当于累积性代价,在图上能转化为分层图的问题,分层图问题核心就是建图。
对于例如我附的裸题这种,就是把图建成k层,这k层就相当于每个点复制k次,或者理解为每一层都是我们原先的那种图,每一层都是正常连边。每层会有0权值的边链接,因为是k层所以最多使用k次免费,表示这一次我们是使用了‘免费‘的次数,复制节点的操作就是:
add(x+j*n,y+j*n,z);
add(y+j*n,x+j*n,z);
add(x+j*n-n,y+j*n,0);
add(y+j*n-n,x+j*n,0);
情况会有 (注意双向):当前的x节点在这一层走到y(花费边权/);走向下一层y(免费)
最后跑一下dij,可能我说的不太清楚,大家可以自己另外搜一下分层图这种题
for(auto x:g[i])
{
if (dis[x][0]>a[x]+w)
{
dis[x][0]=a[x]+w;
q.push(node{dis[x][0],x,0});
}
if (j+1<=k&&dis[x][j+1]>w+1)
{
dis[x][j+1]=w+1;
q.push({dis[x][j+1],x,j+1});
}
}

浙公网安备 33010602011771号