• H 叁佰爱抠的序列(思维欧拉回路)


    题:https://ac.nowcoder.com/acm/contest/4010/H

    题意:找到最大的m,使得存在一个长度为n值域为 [1,m] 的序列,满足任意一组相邻关系都存在。输出为若n>2e6则直接输出m,否则另外输出构造的序列
    分析:相邻关系都要有,那么我们可以联想到n^2的大概样子,然后就m个点完全图可以满足含有相邻关系,更有如果考虑最优,那么存在欧拉回路即可满足条件;

       因为m对于此题来说具有单调性,所以二分地考虑它,m为奇数时,每个点的度数为偶数,必定存在欧拉回路,,m为偶数时,我们利用让含欧拉回路图的性质俩个节点度数为奇数,其余为偶数,方法就是,俩个奇数度数节点连一条边即可;

       最后不足n的部分随便补数即可;

    trick:由于欧拉回路是走边的且要回到起点,所以二分时应该对check部分加1

    #include<cstdio>
    #include<iostream>
    #include<vector>
    #include<algorithm>
    #include<unordered_map>
    using namespace std;
    #define pb push_back
    typedef long long ll;
    const int inf=0x3f3f3f3f;
    const int M=2e6+6;
    struct node{
        int v,nextt,w;
    }e[M<<1];
    int head[M],tot;
    vector<int>ans;
    void addedge(int u,int v){
        e[tot].v=v;
        e[tot].nextt=head[u];
        e[tot].w=0;
        head[u]=tot++;
        e[tot].v=u;
        e[tot].nextt=head[v];
        e[tot].w=0;
        head[v]=tot++;
    }
    ll check(int x){
        if(x%2)
            return 1ll*x*(x-1)/2+1;///n是走的边,最后返回要边数加1
        else
            return 1ll*x*(x-1)/2+(x-2)/2+1;///同理加1
    }
    void dfs(int u){
        for(int &i=head[u];~i;i=e[i].nextt){
            if(e[i].w==1)
                continue;
            e[i].w=e[i^1].w=1;
            dfs(e[i].v);
        }
        ans.pb(u);
    }
    int main(){
        ll n;
        scanf("%lld",&n);
        ll l=1,r=2e9;
        int m;
        while(l<=r){
            int midd=(l+r)>>1;
            if(check(midd)<=n)
                m=midd,l=midd+1;
            else
                r=midd-1;
        }
        if(n>2e6){
            return printf("%d
    ",m),0;
        }
        for(int i=0;i<=m;i++)
            head[i]=-1;
        for(int i=1;i<=m;i++)
            for(int j=i+1;j<=m;j++)
                addedge(i,j);
        if(m%2==0){
            for(int i=3;i<=m;i+=2)
                addedge(i,i+1);
        }
        dfs(1);
        for(int i=ans.size();i<=n;i++)
            ans.pb(1);
        printf("%d
    ",m);
        for(int i=0;i<n;i++)
            if(i!=n-1) printf("%d ",ans[i]);
            else printf("%d
    ",ans[i]);
        return 0;
    }
    View Code
  • 相关阅读:
    创建 SSH Keys
    idea创建管理项目
    springboot拦截器之验证登录
    SpringBoot防XSS攻击
    String,StringBuffer与StringBuilder的区别|线程安全与线程不安全
    算法的时间复杂度和空间复杂度详解
    switch语句以及三种循环语句的总结
    kafka原理简介并且与RabbitMQ的选择
    Kafka、RabbitMQ、RocketMQ等消息中间件的对比 —— 消息发送性能和区别
    RabbitMQ和kafka从几个角度简单的对比
  • 原文地址:https://www.cnblogs.com/starve/p/12927240.html
Copyright © 2020-2023  润新知