Codeforces 1169
1169 B
题意
给你一个pair<int,int> a[]
数组( \(a[i].first≠a[i].second\) ),现在问你是否存在 \(x,y\) ,使得对于每个 \(a[i]\) , \(a[i].first,a[i].second\) 中至少有一个数等于 \(x\) 或等于 \(y\) 。
(样例中第一个数是 \(a\) 中的最大值,第二个数是 \(a\) 的长度)
Examples
input
4 6
1 2
1 3
1 4
2 3
2 4
3 4
output
NO
input
5 4
1 2
2 3
3 4
4 5
output
YES
input
300000 5
1 2
1 2
1 2
1 2
1 2
output
YES
解 1
题目转化:给你一张图,问是否存在两个点,使得所有的边至少经过这两个点中的一个。
乱搞方法:
首先,去重边。(已经保证无自环)
然后先取度数最大的节点,再在剩下的图中取度数最大的节点,如果还有边剩余那就NO
。
特判一种情况:
4 3
1 2
2 3
3 4
解 2
根本没有必要像上面那样做
假设答案是YES
我们不妨设 \(x=a[1].first\) 或 \(x=a[1].second\) ,再对这两种情况分别验证
对于每个 \(a[i]\) ,如果其中不包含 \(x\) ,那么把它的两个元素装桶,最后统计桶的最大值是否等于不包含 \(x\) 的 \(a[i]\) 。
1167 C
题意
有一个数组,你可以进行若干次操作,每次你可以把数组的一个子序列所有元素在模 \(m\) 意义下 \(+1\) ,问你把这个数组变成非严格单调递增的最少需要多少步。
Examples
input
5 3
0 0 0 1 2
output
0
input
5 7
0 6 1 3 2
output
1
解
简单来说就是要最小化每个元素加的值的最大值
所以二分,单调性很好找
Code
#include<bits/stdc++.h>
using namespace std;
const int maxn=300003,INF=1050000000;
int n,m,a[maxn];
bool check(int x){
int mi=0;
for(int i=1;i<=n;i++){
if(m-a[i]+mi<=x)/*a[i]=mi*/;
else{
if(a[i]<mi){
if(mi-a[i]<=x)/*a[i]=mi*/;
else return 0;
}
else mi=a[i];
}
}
return 1;
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)scanf("%d",a+i);
int l=0,r=m,mid,ans;
while(l<=r){
mid=(l+r)>>1;
if(check(mid))ans=mid,r=mid-1;
else l=mid+1;
}
printf("%d\n",ans);
return 0;
}
1169 D
题意
有一个01字符串,现在你需要找到二元组 \((l,r)(l\le r)\) 的对数,满足对于 \(s_{l\dots r}\) ,存在两个数 \(x,k(1\le x,k\le n,l\le x<x+2k\le r)\) ,使得 \(s_x=s_{x+k}=s_{x+2k}\) 。
Examples
input
010101
output
3
input
11001100
output
0
解
乱搞+暴力
Code
#include<bits/stdc++.h>
using namespace std;
const int maxn=300003,INF=1050000000;
int n;
char s[maxn];
long long ans;
int main(){
scanf("%s",s+1);
n=strlen(s+1);
for(int i=n-1,l=n;i>=1;i--){
for(int j=1;i+j+j<=l;j++){
if(s[i]==s[i+j]&&s[i]==s[i+j+j]){
l=i+j+j-1;
}
}
ans+=n-l;
}
printf("%lld\n",ans);
return 0;
}
1169 E
题意
有数组 \(a\) ,长为 \(n\) ,我们说从 \(a_x\) 能到达 \(a_y\) 当且仅当存在数组 \(p\) 满足 \(x = p_1 < p_2 < \dots < p_k=y\) ,且 \(a_{p_i}\& a_{p_{i+1}} > 0\) 。现在有 \(q\) 组询问,每次询问能否从 \(a_x\) 到达 \(a_y\) 。
Example
input
5 3
1 3 0 2 1
1 3
2 4
1 4
output
Fou
Shi
Shi
解
设 \(dp[i][j]\) 表示从 \(a_i\) 出发以第 \(j\) 位往右走最远能走到哪里。
先 \(n\log^2n\) 转移出dp数组,询问时 \(\log n\) 查询是否存在 \(j\) ,使得 \(dp[x][j]\geq y((a[x]\& (1<<j))>0)\) 。
Code
#include<bits/stdc++.h>
using namespace std;
const int maxn=300003,maxlog=21;
int n,Q,a[maxn],last[maxlog],dp[maxn][maxlog];
int main(){
scanf("%d%d",&n,&Q);
for(int i=1;i<=n;i++){
scanf("%d",a+i);
for(int j=0;j<maxlog;j++){
if((a[i]>>j)&1){
dp[i][j]=i;
for(int k=0;k<maxlog;k++){
dp[i][k]=max(dp[i][k],dp[last[j]][k]);
}
last[j]=i;
}
}
}
while(Q--){
int x,y,flag=0;
scanf("%d%d",&x,&y);
for(int i=0;i<maxlog;i++){
if(((a[x]>>i)&1)&&dp[y][i]>=x){flag=1;break;}
}
puts(flag?"Shi":"Fou");
}
return 0;
}