牛客周赛 Round 85【题解完成】

99 阅读4分钟
题目难度知识点
A 小紫的均势博弈签到
B 小紫的劣势博弈签到
C 小紫的01串操作思维
D 小紫的优势博弈思维
E 小紫的线段染色贪心
F 小紫的树上染色★★二分/树

image.png 怎么人均会F,确实没想到二分直接放弃了,看题解搞二分但是居然不会写。后来才发现这么简单。呃呃呃属实太菜了。

小紫的均势博弈

#include<bits/stdc++.h>
using namespace std;
const int N=1e4+10;
int main(void)
{
    int n; cin>>n;
    if(n&1) puts("kou");
    else puts("yukari");
    return 0;
}

小紫的劣势博弈

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
typedef long long int LL;
LL a[N];
int main(void)
{
    int n; cin>>n;
    for(int i=0;i<n;i++) cin>>a[i];
    sort(a,a+n);
    LL sum=0;
    for(int i=0;i<n;i++){
        if(i&1) sum-=a[i];
        else sum+=a[i];
    }
    cout<<sum;
    return 0;
}

小紫的01串操作

不会剪短写法,就写了个暴力,但是可以看到优化后的字符串长度过大一定无解,故只需判断一个很小的长度就行了。

#include<bits/stdc++.h>
using namespace std;
void solve()
{
    string s; cin>>s;
    vector<char>ve;
    int n=s.size();
    for(int i=0;i<n;i++)
    {
        int j=i;
        while(j+1<n&&s[j+1]==s[i]) j++;
        i=j;
        ve.push_back(s[i]);
    }
    int flag=0;
    if(ve.size()<=3) flag=1;
    else if(ve.size()>3&&ve.size()<=10)
    {
        for(int i=0;i<ve.size();i++)
        {
            vector<char>temp;
            temp=ve;
            if(ve[i]=='0')
            {
                temp[i]='1';
                int cnt=0;
                for(int j=0;j<ve.size();j++)
                {
                    int k=j;
                    while(k+1<ve.size()&&temp[k+1]==temp[j]) k++;
                    j=k;
                    cnt++;
                }
                if(cnt<=3) flag=1;
            }
            if(ve[i]=='1')
            {
                temp[i]='0';
                int cnt=0;
                for(int j=0;j<ve.size();j++)
                {
                    int k=j;
                    while(k+1<ve.size()&&temp[k+1]==temp[j]) k++;
                    j=k;
                    cnt++;
                }
                if(cnt<=3) flag=1;
            }
        }
    }
    if(flag) puts("Yes");
    else puts("No");
}
int main(void)
{
    int t; cin>>t;
    while(t--) solve();
    return 0;
}

将润色后的字符串如果长度小于等于5必可以,这个可以试一下发现是一定的。

#include<bits/stdc++.h>
using namespace std;
int main(void)
{
    int t; cin>>t;
    while(t--)
    {
        string s; cin>>s;
        int cnt=0;
        for(int i=0;i<s.size();i++)
        {
            int j=i;
            while(j+1<s.size()&&s[j+1]==s[i]) j++;
            i=j;
            cnt++;
        }
        if(cnt<=5) puts("Yes");
        else puts("No");
    }
    return 0;
}

小紫的优势博弈

image.png

暴力模拟即可,时间复杂度是线性的。

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int s0[N],s1[N];
int main(void)
{
    int n; cin>>n;
    string s; cin>>s;
    s="_"+s;
    for(int i=1;i<=n;i++)
    {
        s0[i]=s0[i-1];
        s1[i]=s1[i-1];
        if(s[i]=='0') s0[i]++;
        if(s[i]=='1') s1[i]++;
    }
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        int j=i+1,cnt0=0,cnt1=0;
        while(j<=n)
        {
            if(s[j]=='1') cnt1++;
            else if(s[j]=='0') cnt0++;
            if( cnt0%2==0 && cnt1%2==0 &&(cnt0 || cnt1))
            {
                ans++;
                break;
            }
            j++;
        }
    }
    printf("%.10lf",ans*1.0/n);
    return 0;
}

image.png

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
int cnt0[N],cnt1[N];
int main(void)
{
    int n; cin>>n;
    string s; cin>>s;
    s=" "+s;
    for(int i=1;i<=n;i++)
    {
        cnt0[i]=cnt0[i-1]+(s[i]=='0');
        cnt1[i]=cnt1[i-1]+(s[i]=='1');
    }
    map<pair<int,int>,int>last_pos; 
    int ans=0;
    for(int i=1;i<=n;i++)
    {
        last_pos[{cnt0[i]%2,cnt1[i]%2}]=i;
    }
    for(int i=1;i<=n;i++)
    {
        int j=last_pos[{cnt0[i]%2,cnt1[i]%2}];
        if(j>i) ans++;
    }
    printf("%.8lf",ans*1.0/n);
    return 0;
}

小紫的线段染色

说实话不会,纯猜的要么左端点排,要么右端点排。想的右端点但是歪了。

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct node
{
    int l,r,id;
};
bool cmp(node a,node b)
{
    return a.l<b.l;
}
vector< node >ve;
int st[N];
int main(void)
{
    int n; cin>>n;
    for(int i=0;i<n;i++)
    {
        int l,r; cin>>l>>r;
        ve.push_back({l,r,i+1});
    }
    sort(ve.begin(),ve.end(),cmp);
    if(n==1)
    {
        cout<<1<<'\n'<<ve[0].id;
    }else
    {
        memset(st,-1,sizeof st);
        vector<int>red,green; red.push_back(ve[0].r);
        green.push_back(ve[1].r);
        vector<int>ans; ans.push_back(ve[1].id);
        for(int i=2;i<n;i++)
        {
            if(ve[i].l>red.back() && red.back()<=green.back() ) red.push_back(ve[i].r);
            else if(ve[i].l>green.back()) green.push_back(ve[i].r),ans.push_back(ve[i].id);
            else 
            {
                cout<<-1;
                return 0;
            }
        }
        cout<<ans.size()<<endl;
        for(int i=0;i<ans.size();i++) cout<<ans[i]<<" ";
    }
    return 0;
}

小紫的树上染色

image.png

#include<bits/stdc++.h>
using namespace std;
const int N=1e5*5+10;
vector<int>ve[N];
int dp[N],n,k,cnt;
void dfs(int u,int fa,int x)
{
    dp[u]=1;
    for(int i=0;i<ve[u].size();i++)
    {
        int j=ve[u][i];
        if(j==fa) continue;
        dfs(j,u,x);
        dp[u]+=dp[j];
    }
    if(dp[u]>x)
    {
        cnt++;
        dp[u]=0;
    }
}
int check(int x)
{
    cnt=0;
    for(int i=0;i<=n;i++) dp[i]=0;
    dfs(1,0,x);
    return cnt;
}
int main(void)
{
    cin>>n>>k;
    for(int i=1;i<=n-1;i++)
    {
        int a,b; cin>>a>>b;
        ve[a].push_back(b);
        ve[b].push_back(a);
    }
    int l=0,r=n;
    while(l<r)
    {
        int mid=(l+r)/2;
        if(check(mid)<=k) r=mid;
        else l=mid+1;
    }
    cout<<l;
    return 0;
}