• 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
    ",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;
    }
    
  • 相关阅读:
    021.day21 反射 Class类 反射常用操作
    020.day20 线程概述 多线程优缺点 线程的创建 线程常用方法 生命周期 多线程同步
    019.day19 缓冲流 对象流 标准输入输出流
    018.day18 map集合如何实现排序 File类 IO流 字节流 字符流 编码
    017.day17 Map接口 克隆 treeSet集合排重缺陷
    016.day16 HashSet TreeSet 比较器Comparable Comparator
    015.day15
    014.day14
    013.day13
    线程
  • 原文地址:https://www.cnblogs.com/BlogOfchc1234567890/p/11047361.html
Copyright © 2020-2023  润新知