Day4 Codeforces Round #562 (Div. 2 A,B,C,D)&&POJ1489(最小生成树)

这些题是昨天就写了的,事情太多,博客拖到现在才写

Codeforces Round #562 (Div. 2)

A:

思路:按题意模拟一下坐车过程,可以先预处理一下a,x,b,y,将其值全部减一,然后模拟的时候在加一减一的基础上每次加一个mod,再模mod就行了,也可以不预处理a,x,b,y,这样的话就得特判处理一下到圆环边界的情况。

不预处理代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=1e3+9;
int main(){
    int i,j,k,n,a,b,x,y;

    cin>>n>>a>>x>>b>>y;
    i=a,j=b;
    int mod=n+1,flag=0;
    while(i!=x&&j!=y){
        i=(i+mod+1)%mod;j=(j+mod-1)%mod;
        if(i==0)i=1;
        if(j==0)j=n;
        if(i==j){
            flag=1;
        }
    }
    if(flag)cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
}

B:

思路:我们枚举第一对数中的两个数,每次枚举选一个数确定数对中的一个数,然后筛选出所有有这个数的数对,将他们剔除掉,然后我们再来将剩下数对的数计算出现次数,如果有数出现次数等于剩下的数对数,则有答案,否则没有

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=3e5+9;
int a[maxn][2],vis[maxn],mp[maxn];
vector<int>vec;
bool cmp(int a,int b){
    return a>b;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie();
    int i,j,k,n,m;
    cin>>n>>m;
    for(i=0;i<m;i++){
        for(j=0;j<2;j++){
            cin>>a[i][j];
        }
    }
    int x=a[0][0],cnt=1;
    for(i=1;i<m;i++){
        int flag=0;
        for(j=0;j<2;j++){
            if(a[i][j]==x)flag=1;
        }
        if(flag)vis[i]=1,cnt++;
    }
    for(i=1;i<m;i++){
        if(!vis[i]){
            for(j=0;j<2;j++){
                mp[a[i][j]]++;
            }
        }
    }
    for(j=0;j<=n;j++){
        vec.push_back(mp[j]);
    }
    sort(vec.begin(),vec.end(),cmp);
    if(vec[0]>=m-cnt){
        cout<<"YES"<<endl;
        return 0;
    }
    vec.clear();
    memset(vis,0,sizeof(vis));
    memset(mp,0,sizeof(mp));
    x=a[0][1],cnt=1;
    for(i=1;i<m;i++){
        int flag=0;
        for(j=0;j<2;j++){
            if(a[i][j]==x)flag=1;
        }
        if(flag)vis[i]=1,cnt++;
    }
    for(i=1;i<m;i++){
        if(!vis[i]){
            for(j=0;j<2;j++){
                mp[a[i][j]]++;
            }
        }
    }
    for(j=0;j<=n;j++){
        vec.push_back(mp[j]);
    }
    sort(vec.begin(),vec.end(),cmp);
    if(vec[0]>=m-cnt){
        cout<<"YES"<<endl;
        return 0;
    }
    cout<<"NO"<<endl;
}

C:

思路:

二分枚举答案,贪心check答案是否合法。假若我们枚举的答案为k的话,则我们最多的操作次数为k,对于每个数,我总是贪心进行1~k次操作(为什么允许操作少于k次,这样不是不能保证我check时一定对序列进行k此操作吗?实际上不能保证也没关系,如果我通过小于k次的操作次数x保证了序列的合法性,那么我接下来的二分一定能扫到小于等于x次的答案)让改变后的数既维持非递减性又让它比原数小。

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=3e5+9;
int a[maxn],n,mod;
bool check(int k){
    int u=0;
   // cout<<k<<endl;
    for(int i=1;i<=n;i++){
        int x=a[i],y=(a[i]+k)%mod;
        //int z=y<x?u:x;
        if(x<u&&k<u-x){
             //   cout<<endl;
            return false;
        }
        else if(x<u&&k>=u-x){
            continue;
        }
        if(x>=u&&k>=mod-x+u){
            u=u;
        }
        else{
            u=x;
        }
        //cout<<u<<' ';
    }
    //cout<<endl;
    return true;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int i,j,k;
    cin>>n>>mod;
    for(i=1;i<=n;i++){
        cin>>a[i];
    }
    int l=0,r=mod;
    while(l<r){
        int mid=(l+r)>>1;
        if(check(mid)){
            r=mid;
        }
        else l=mid+1;
    }
    cout<<r<<endl;
}

D:

思路:

双指针找一下l,r,我们不妨令r总是等于x+2k的位置,每次我们找到一个l,r区间满足条件则ans+=len-r(len代表string.size,由于左指针是从0开始的,所有ans+=len-r+1是错误的),然后向右移动左指针,否则更改x值,如果r-2*k<l的话则向右移动右指针。至于为什么我们只需要额外考虑r+1,r+2,...,len-1的贡献,而不需要考虑0,1,2...l-1的贡献,这是因为我们我们的左指针是从1,2...l-1移动到l来的,如果l...r满足条件,则1...r,2...r,3...r,l-1...r必定也满足条件,所有对于一个合法的l...r,左指针作为0,1,2...l-1的贡献已经计算过了,不需要重复计算。

代码:

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define ll long long
const ll maxn=3e5+9;
int main(){
    ll i,n;
    string s;
    cin>>s;
    ll len=s.size();
    ll j=0;
    ll ans=0;;
    for(i=0;i<len;i++){
        ll flag=0,k=1;
        while(j<len){//cout<<j<<' '<<i<<endl;
            if(j-2*k<i){
                j++;
                k=1;
                continue;
            }
            if(s[j]==s[j-k]&&s[j]==s[j-2*k]){

                flag=1;
                break;
            }
            k++;
        }
        if(flag)ans+=len-j;
        else break;
    }
    cout<<ans<<endl;
}

POJ 1789

思路:将运输车抽象化为点,先计算出任意两点之间的距离,然后我们按边权排序,简单打一下kruskal的板子就行了

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
#define inf 0x3f3f3f3f
const int maxn=2e3+9;
int mp[maxn][maxn];
string s[maxn];
struct node{
    int u,v,val;
}edge[maxn*maxn];
bool cmp(node a,node b){
    return a.val<b.val;
}
int f[maxn];
void init(){
    for(int i=0;i<=maxn;i++)f[i]=i;
}
int find(int v){
    if(f[v]==v)return v;
    f[v]=find(f[v]);
    return f[v];
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);
    int i,j,k,n;
    while(cin>>n&&n){
    for(i=0;i<n;i++){
        cin>>s[i];
    }
    int cnt=0;
    for(i=0;i<n;i++){
        for(j=i+1;j<n;j++){
            int dis=0;
            for(k=0;k<7;k++){
                if(s[i][k]!=s[j][k])dis++;
            }
            edge[cnt].val=dis;
            edge[cnt].u=i;
            edge[cnt++].v=j;
        }
    }
    init();
    sort(edge,edge+cnt,cmp);
    int ans=0;
    for(i=0;i<cnt;i++){
       // cout<<edge[i].val<<' ';
        int u=edge[i].u,v=edge[i].v;
        int t1,t2;
        t1=find(u);t2=find(v);
       // cout<<t1<<' '<<t2<<endl;
        if(t2!=t1){
            f[t2]=t1;
           // cout<<123<<endl;
            ans+=edge[i].val;
        }
    }
    cout<<"The highest possible quality is 1/";
    cout<<ans<<'.'<<endl;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值