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;
}

转载于:https://www.cnblogs.com/BlogOfchc1234567890/p/11047361.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值