$$ \newcommand{\seq}[2]{{#1}_{1},{#1}_{2},\cdots,{#1}_{#2}} \newcommand{\num}[1]{1,2,\cdots,#1} \newcommand{\stra}[2]{\begin{bmatrix}#1 \\ #2\end{bmatrix}} \newcommand{\strb}[2]{\begin{Bmatrix}#1 \\ #2\end{Bmatrix}} \newcommand{\dw}[1]{\underline{#1}} \newcommand{\up}[1]{\overline{#1}} $$

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;
}
posted @ 2019-06-18 20:05  chc_1234567890  阅读(149)  评论(0编辑  收藏  举报