0%

思路讲解

https://acm.hdu.edu.cn/contest/problem?cid=1172&pid=1005

这个题目的思路还是比较简单的,建虚拟点,

传送门

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
while (!pq.empty()) {
auto [node,dis]=pq.front();
pq.pop_front();
if(dis>Dis[node]) continue;
Dis[node]=dis;
for(auto&v:g[node]){
if(node<=N){
if(dis+1>=Dis[v]) continue;
Dis[v]=dis+1;
pq.PB({v,dis+1});
}else{
if(dis>=Dis[v]) continue;
Dis[v]=dis;
pq.PF({v,dis});
}
}
}

AC代码

https://codeforces.com/contest/1941/submission/336750153

心路历程(WA,TLE,MLE……)

思路讲解

要多写,如果实在没有思路就数学化。

参考思路如下。

https://www.luogu.com.cn/article/7xrsn748

不难发现,我们要最小化下面👇。

i=1n(s[i]s[i])2i=1ns[i]2+s[i]22s[i]s[i]\sum_{i=1}^{n}(s[i]-s'[i])^2 \Rightarrow \sum_{i=1}^{n}s[i]^2+s'[i]^2-2s[i]s'[i]

Codeforces Round 1046 (Div. 2)——D. For the Champion

常数分离以后,我们其实就是要最大化👇。

相当于我们要最大化 i=1ns[i]s[i]\sum_{i=1}^{n}s[i]s'[i] 。不过我们发现好像没什么用?非常有用,我们就知道了,1 1 非常重要,要尽量多的出现1 1,其他不重要

当然,如果光有这个想法是不行的。我们还需要用到分块思想。

首先那,分块,我们自然是同时只能按照一个字符串分块的,因此我们按照 ss 可不可以交换分块。

但是,我们按照 ss 分块以后,我们可以再对 ss' 进行分块。这个听起来很抽象是吧?其实也简单,就是说 ss’ 其实如果不是落在整段 ss 可交换块上,可以部分落在 s 的可交换块上,然后我们的策略其实就是尽量多的出现1 1。

AC代码

心路历程(WA,TLE,MLE……)

思路讲解

https://leetcode.cn/problems/longest-substring-with-at-least-k-repeating-characters/description/

其实就是双指针。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void cal(ll uni){
vll cnt(28);
ll l=0,r=0;
ll cur=0,bigk=0;
while (r<SZ(s)) {
if(cur<=uni){
int idx=s[r]-'a';
if(cnt[idx]==0) ++cur;
cnt[idx]++;
if(cnt[idx]==K) ++bigk;
++r;
}else{
int idx=s[l]-'a';
if(cnt[idx]==K) --bigk;
--cnt[idx];
if(cnt[idx]==0) --cur;
++l;
}
if(cur==uni && bigk==cur){
ans=max(ans,r-l);
}
}
}

AC代码

AC

https://leetcode.cn/problems/longest-substring-with-at-least-k-repeating-characters/submissions/658772401/

心路历程(WA,TLE,MLE……)

思路讲解

1
2
// 整体思路就是我们如果发现如果两者起始位置不同,那么是不会有相交的,或者相交一次
// 简单而言,就是必须先有一次相交,接着运动方向一样,才能有相交,否则就直接穿过去了
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 在同一点并且操作序列相同
if(a==b && opa==opb){
ans+=mn;
}else{
auto f=[&](ll dis){
Point c=oper(a, opa,dis),d=oper(b, opb, dis);
return mandis(c, d);
};
ll l=1,r=mn;
while (l<r) {
ll mid=l+r>>1;
// if(f(mid)<=f(mid+1)){
// 从mid点(或其前)开始,函数开始单调递增
if(f(mid+1)-f(mid)>=0){
r=mid;
}else{
l=mid+1;
}
}
if(f(l)==0){
++ans;
}
}

AC代码

https://atcoder.jp/contests/abc421/submissions/68978595

心路历程(WA,TLE,MLE……)