2020牛客寒假算法基础集训营6【无E H I】

题目来源:https://ac.nowcoder.com/acm/contest/3007#question
这场又有好多AK的,我tcl… 可能会补2题左右,保证不咕~


A - 配对

先对两个序列从小到大排序,假如选第k大的,那我们肯定不能让第k大的这个碰到两个序列前1 - k 的元素,忽略他们,然后后面的头+尾 排个序取最小值

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,string> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-10;
const double pi=acos(-1);
int n,m;
int f[N],g[N];
int p[N];
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int main()
{
    r(n); r(m);
    FOR(i,1,n) r(f[i]);
    FOR(i,1,n) r(g[i]);
    sort(f+1,f+n+1);
    sort(g+1,g+n+1);
    FOR(i,n-m+1,n){
        p[i-n+m]=f[i]+g[n-i+n-m+1];
    }
    sort(p+1,p+m+1);
    cout<<p[1]<<endl;
    return 0;
}


B - 图

这题应该就是类似于记忆化搜索,搜过的点标记上它的值,然后可以O(n)解决,难点就在于环的处理。但是这样想,从一个点开始搜,它最终的结局要么是撞到自己刚刚搜到的点成环,要么是碰到已经搜过的点把这个点的值+1即可。
在这里插入图片描述

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,string> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-10;
const double pi=acos(-1);
int n,m;
int to[N];
bool vis[N];
int step[N];
int num[N];
int ans,loop;
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int dfs(int x,int stp)
{
    //cout<<x<<' '<<stp<<endl;
    step[x]=stp;
    int t=to[x];
    if(vis[t]==0){
        vis[t]=1;
        int res=dfs(t,stp+1);
        if(loop!=0){
            if(loop==x){
                loop=0;
            }
            return num[x]=res;
        }
        else{
            return num[x]=res+1;
        }
    }
    else{
        if(num[t]>0) return num[x]=num[t]+1;
        else if(num[t]==0){
            loop=t;
            if(t==x) loop=0;
            return num[x]=step[x]-step[t]+1;
        }
    }
}
int main()
{
    r(n);
    FOR(i,1,n){
        r(to[i]);
    }
    ans=0;
    FOR(i,1,n){
        if(!vis[i]){
            vis[i]=1;
            loop=0;
            dfs(i,1);
        }
    }
    FOR(i,1,n){
        ans=max(num[i],ans);
       // cout<<num[i]<<' ';
    }
    //cout<<endl;
    cout<<ans<<endl;
    return 0;
}


C - 汉诺塔

这题真的感觉我最近在哪里做过类似的题,应该是cf上!
首先对x从大到小排序,然后从左到右加入set,加之前先看他能不能在set中找到比他的y小的最大的点放在他上面

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,int> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-10;
const double pi=acos(-1);
int n,m;
struct node
{
    int x,y,id;
    bool operator< (node a){
        return x<a.x;
    }
}f[N];
int val[N];
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int main()
{
    r(n);
    FOR(i,1,n){
        r(f[i].x); r(f[i].y);
        f[i].id=i;
    }
    sort(f+1,f+n+1);
    set<pt> s;
    int num=0;
    FOR(i,1,n){
        if(s.size()){
            set<pt>::iterator it=s.lower_bound(mp(f[i].y,0));
            if(it!=s.begin()){
                it--;
                if(val[it->second]==0){
                    val[it->second]=++num;
                    val[f[i].id]=num;
                }
                else{
                    val[f[i].id]=val[it->second];
                }
                s.erase(it);
            }
        }
        s.insert(mp(f[i].y,f[i].id));
    }
    FOR(i,1,n){
        if(val[i]==0) val[i]=++num;
    }
    cout<<num<<endl;
    FOR(i,1,n) cout<<val[i]<<' ';
    cout<<endl;
    return 0;
}

D - 重排列

反着思考,我们找不满足的 和总数相减即可
先对两个序列排序,这不会影响结果(可以理解的吧)
然后只要我们满足任意一个地方大于 他就是不满足的 没问题吧.
遍历一遍,对于当前的点i 我们找比这个点大的有多少个(二分搜索) 然后在这个点用比他大的点,那么后面任意怎么排都行ans=(ans+mult*cnt_h%mod*cc[n-i]%mod)%mod;
但是这个mult是干嘛的? 如果我们选不大于这个点的那就要看下一个点大不大嘛

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,char> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-10;
const double pi=acos(-1);
LL n,m;
int f[N];
int g[N];
LL cc[N];
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int main()
{
    r(n);
    cc[0]=1;
    FOR(i,1,n){
        cc[i]=cc[i-1]*i%mod;
    }
    FOR(i,1,n){
        r(f[i]);
    }
    FOR(i,1,n) r(g[i]);
    sort(g+1,g+n+1);
    sort(f+1,f+n+1);
    LL ans=0,mult=1;
    FOR(i,1,n){
        LL cnt_l=upper_bound(f+i,f+n+1,g[i])-f-i;
        LL cnt_h=(n-i+1)-cnt_l;
        ans=(ans+mult*cnt_h%mod*cc[n-i]%mod)%mod;
        //cout<<ans<<endl;
        if(cnt_h==n-i+1||cnt_h==0){
            break;
        }
        else{
            mult=mult*cnt_l%mod;
        }
    }

    LL res=(cc[n]-ans+mod)%mod;
    cout<<res<<endl;
    return 0;
}


E - 立方数

狂T不止


F - 十字阵列

计算每次操作的贡献即可,因为每次操作的每个格子的i+j是很容易算出来的(m*x+n*y-x-y)+(n+1)*n/2+(m+1)*m/2;

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,string> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-10;
const double pi=acos(-1);
int n,m;
int f[N],g[N];
int p[N];
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int main()
{
    int k;
    r(n); r(m); r(k);
    LL ans=0;
    FOR(i,1,k){
        int x,y,z;
        rrr(x,y,z);
        LL dmg=(m*x+n*y-x-y)+(n+1)*n/2+(m+1)*m/2;
        ans=(ans+dmg*z%mod)%mod;
        //cout<<ans<<endl;
    }
    cout<<ans<<endl;
    return 0;
}


G - 括号序列

就是括号匹配…

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,string> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-10;
const double pi=acos(-1);
int n,m;
char str[N];
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int main()
{
    int t;
    r(t);
    while(t--){
        r(n);
        scanf("%s",str+1);
        stack<char> s;
        FOR(i,1,n){
            if(s.size()){
                if(str[i]==')'&&s.top()=='('){
                    s.pop();
                }
                else{
                    s.push(str[i]);
                }
            }
            else{
                s.push(str[i]);
            }
        }
        cout<<s.size()<<endl;
    }
    return 0;
}


H - 云


I - 导航系统


J - 签到题

设三个圆的半径分别为a b c,那三个边长即为a+b,b+c,a+c
a + b + c = ( x + y + z ) / 2 a+b+c=(x+y+z)/2 (x,y,z为输入的边长)如果能构成三角形,那么很容易知道一边小于两边之和,设 x = a + b , y = a + c , z = b + c c = ( x + y + z ) / 2 x , b = ( x + y + z ) / 2 z , a = ( x + y + z ) / 2 y x=a+b,y=a+c,z=b+c 易得c=(x+y+z)/2-x,b=(x+y+z)/2-z,a=(x+y+z)/2-y 其中a b c一定都大于0 故一定存在!

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<vector>
#include<set>
#include<map>
#include<string>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define mp(x,y) make_pair(x,y)
#define r(x) read(x)
#define rrr(x,y,z) read(x);read(y);read(z)
#define FOR(i,l,r) for(int i=l;i<=r;i++)
using namespace std;
typedef long long LL;
typedef pair<int,string> pt;
const int N=1e6+5;
const int M=2e3+5;
const int INF=0x7fffffff;
const int mod=1e9+7;
const double eps=1e-10;
const double pi=acos(-1);
int n,m;
template<class T>
inline void read(T &x)
{
    char c; x=1;
    while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;
    T res=c-'0';
    while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';
    x*=res;
}
int main()
{
    int a,b,c;
    rrr(a,b,c);
    double tot=(a+b+c)*1.0/2;
    if(a+b>c&&a+c>b&&b+c>a){
        if(tot>a&&tot>b&&tot>c){
            cout<<"Yes\n";
            double f[4];
            f[1]=tot-a;
            f[2]=tot-b;
            f[3]=tot-c;
            sort(f+1,f+4);
            printf("%.2f %.2f %.2f\n",f[1],f[2],f[3]);
        }
        else{
            cout<<"No\n";
        }
    }
    else{
        cout<<"wtnl\n";
    }
    return 0;
}


发布了75 篇原创文章 · 获赞 93 · 访问量 9788

猜你喜欢

转载自blog.csdn.net/weixin_43890662/article/details/104331806