C. Increasing by Modulo
这个题是 一个 二分答案题。
首先我们二分一个值出来,然后 check, 关键是如何 check。
我们首先假定最小的一个值 是 0,
然后遍历一遍数组,把数组上的值在允许的范围内尽量改小就好,
如果最后满足题目要求,那么这个二分的数就是满足条件的。
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+100;
int a[N],b[N],n,m;
bool check(int k){
int cnt = 0,tmp;
for (int i = 0; i < n; ++i){
if (a[i] >= cnt){
tmp = (m - a[i]) + cnt;
if (tmp > k) cnt = a[i];
} else {
tmp = (cnt - a[i]);
if (tmp > k) return false;
}
}
return true;
}
int main(){
int l = 0, r = N - 10,mid;
scanf("%d%d",&n,&m);
for (int i = 0; i < n; ++i)
scanf("%d",&a[i]);
int ans;
while(l <= r){
mid = (l + r) >> 1;
if (check(mid)){
r = mid - 1;
ans = mid;
} else l = mid + 1;
}
printf("%d\n",ans);
return 0;
}
D - Good Triple
直接暴力就可以了,
for 循环一边数据,然后暴力向前找满足题目要求的点, ans 加上去就好了。
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+100;
int n;
char s[N];
int main(){
long long ans = 0,l = 0;
scanf("%s",s+1);
n = strlen(s+1);
for (int i = 3; i <= n; ++i){
for (int j = i - 2; j >= l; j -= 2)
if (s[i] == s[j] && s[(i + j) >> 1] == s[i]){l = j; break; }
ans += l;
}
printf("%lld\n",ans);
return 0;
}
E - And Reachability
我们有 f[i][j] 代表 从i 这个位置开始, 最小能到达的位置 y ,这个 y 位置上的值 的二进制的 j 位是1,且从 i 位置到 y 位置,满足题目要求。
即 相当于 i 为 题目中的 x, y 为 y,且 y 位置上的 数的二进制的 j 位 为 1。
#include<bits/stdc++.h>
using namespace std;
const int N = 3e5+100;
const int INF = 0x3f3f3f3f;
int a[N],w[25],f[N][25];
int n,m;
void init(){
memset(f, INF , sizeof f);
memset(w , -1 , sizeof w);
for (int i = 1; i <= n; ++i)
scanf("%d",&a[i]);
for (int i = n; i > 0; --i)
for (int j = 0; j < 25; ++j)
if ((a[i] >> j) & 1){
for (int k = 0; k < 25; ++k)
if (w[j] != -1) f[i][k] = min(f[i][k],f[w[j]][k]);
w[j] = i; f[i][j] = min(f[i][j],i);
}
}
int main(){
scanf("%d%d",&n,&m);
init();
int x,y;
bool vis;
for (int i = 0; i < m; ++i){
scanf("%d%d",&x,&y);
vis = 0;
for (int j = 0; j < 25; ++j)
if ((a[y] >> j)&1 && (f[x][j] <= y)){
vis = 1; break;
}
vis == 1? puts("Shi"): puts("Fou");
}
return 0;
}