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
",ans);
return 0;
}
1169 D
题意
有一个01字符串,现在你需要找到二元组 ((l,r)(lle r)) 的对数,满足对于 (s_{ldots r}) ,存在两个数 (x,k(1le x,kle n,lle x<x+2kle 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
",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) 位往右走最远能走到哪里。
先 (nlog^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;
}