模拟赛三 - 补题报告

目录

一、题目报告

二、赛中概况

三、题目概况

T1.虚假的一般图最小匹配(match)

题目大意

题目解析

正解代码

T2.序列删除与填充(delfill)

题目大意

题目解析

正解代码

T3.T4.

四、总结


一、题目报告

T1 贪心 拿了 70分

T2 贪心 拿了 50分

T3 骗分 骗了 10分

T4 骗分 骗了 15分

二、赛中概况

        比赛时,先看了看第一题(虚假的一般图最小匹配),嗯,简单的想到了一个贪心的做法,花了大约半个小时打出来了,但是感觉有问题(是真的有问题),就尝试去用区间dp解决,但是推了很久都没有推对,果断放弃。

        再看看第二题(序列删除与填充),嗯,没有暴力思路,所以就尝试去打正解一个可行的思路,推了大约30min,又打了接近20min的代码,做出来了,感觉应该大概可能或许有概率AC(然而是我想多了)。

        第三题(虚假的斯坦纳树),斯坦纳树?没听过,看了看题目描述,看不太懂,放弃。

        第四题(虚假的树直径)今天的虚假东西可真多啊,哎,我貌似会树的直径唉,看了看题,我又想多了。

        由于实在不会三四题,甚至连暴力思路都没有,就只好输出了一些“1”,竟然骗了25分!?(数据有点水吧)

三、题目概况

T1.虚假的一般图最小匹配(match)

题目大意

一个n个点的完全图,取出2*mm个点,求最小的边权\left | a{_{i}}-a{_{j}}\right |总和。

题目解析

这是一个完全图,说明任意两点之间都有边相连。要求最小值,那么肯定是相邻值的两个点之间的扁选择出来最优,就可以给所有点先按照值排序,求出每每相邻的两个点之间的边权,去利用dp求出最小值即可。

正解代码

#include <cstdio>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <list>
using namespace std;

#define bug printf("--------\n");
#define debug(x) cout << #x << '=' << x << endl;
#define file(FILENAME) freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout);
#define rep(i, a, b) for(int (i) = (a); (i) <= (b); ++(i))
#define inv(x) qpow((x), mod - 2)
#define pb push_back
#define mk make_pair
#define mem(t, v) memset((t), (v), sizeof (t));
#define DBG cerr << __LINE__  << ' ' << __FUNCTION__ << endl;
#define CLOSE ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);

#define N 5005
#define M 10005
#define inf 0x3f3f3f3f3f3f3f3f
#define mod 10007

typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { while (a ^= b ^= a ^= b %= a); return b; }
ll ppow(ll x, ll y) { ll sum = 1; while (y) { if (y & 1) sum *= x; y >>= 1, x *= x; } return sum; }
bool prime(ll x) { for (int i = 2; i * i <= x; i++) { if (x % i == 0) return false; } return true; }

// ll n, m, l, k, p, i;
// ll a[N], b[N];
// bool vis[N];
// stack<ll> st;
// queue<ll> q;
// map<ll,ll> mp;
// vector<ll> v;
// char c;
// string s;
// ll ans, cnt, sum, num;
// struct node {
//     ll x;
//     ll y;
// }d[N];
ll n,m;
ll a[N];
ll dp[N][N];

int main() {
    // file("match")
    // CLOSE
    cin>>n>>m;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        dp[0][i]=dp[1][i]=inf;
    }
    sort(a+1,a+n+1);
    for(int i=2;i<=n;i++){
        for(int j=1;j<=m;j++){
            dp[i][j]=dp[i-1][j];
            dp[i][j]=min(dp[i-2][j-1]+a[i]-a[i-1],dp[i][j]);
        }
    }
    cout<<dp[n][m];
    return 0;
}

T2.序列删除与填充(delfill)

题目大意

给定一个长度为n的序列,从中删除并插入一些数,求出字典序最小的序列

题目解析

贪心,去通过条件逐一分解成小问题去解决。

推理过程暂无...

正解代码

不知是怎样的玄学问题,它没问题却过不了,当个乐子看吧。

#include <cstdio>
#include <string>
#include <iostream>
#include <cstdlib>
#include <cmath>
#include <cstring>
#include <algorithm>
#include <stack>
#include <queue>
#include <map>
#include <vector>
#include <set>
#include <list>
using namespace std;

#define bug printf("--------\n");
#define debug(x) cout << #x << '=' << x << endl;
#define file(FILENAME) freopen(FILENAME ".in", "r", stdin), freopen(FILENAME ".out", "w", stdout);
#define rep(i, a, b) for(int (i) = (a); (i) <= (b); ++(i))
#define inv(x) qpow((x), mod - 2)
#define pb push_back
#define mk make_pair
#define mem(t, v) memset((t), (v), sizeof (t));
#define DBG cerr << __LINE__  << ' ' << __FUNCTION__ << endl;
#define CLOSE ios::sync_with_stdio(false); cin.tie(0); cout.tie(0);

#define N 200005
#define M 10005
#define inf 0x3f3f3f3f
#define mod 10007

typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { while (a ^= b ^= a ^= b %= a); return b; }
ll ppow(ll x, ll y) { ll sum = 1; while (y) { if (y & 1) sum *= x; y >>= 1, x *= x; } return sum; }
bool prime(ll x) { for (int i = 2; i * i <= x; i++) { if (x % i == 0) return false; } return true; }

ll a[N],aa[N],b[N],k;
bool vis[N];

int main() {
    // file("delfill")
    // CLOSE
    ll t;
    cin>>t;
    vis[0]=b[0]=0;
    while(t--){
        ll n;
        cin>>n;
        ll del=-1;
        int flag=-1;
        memset(a,0,sizeof a);
        memset(b,0,sizeof b);
        memset(vis,0,sizeof vis);
        k=0;
        a[0]=inf;
        for(int i=1;i<=n;i++){
            cin>>a[i];
            aa[i]=a[i];
            vis[a[i]]=1;
            if(a[i]==0&&flag==-1)flag=i;
        }
        if(flag==-1){
            del=n;
            for(int i=2;i<=n;i++){
                if(a[i]<a[i-1]){
                    del=i-1;
                    break;
                }
            }
        }
        else{
            bool flag_bool=0;
            for(int i=2;i<=flag-1;i++){
                if(a[i]<a[i-1]){
                    del=i-1;
                    vis[a[del]]=0;
                    flag_bool=1;
                    break;
                }
            }
            bool nomin=0;
            if(!flag_bool){
                ll maxx_need=0;
                for(int i=1;i<=n;i++){
                    if(!vis[i]){
                        maxx_need=i;
                        break;
                    }
                }
                if(flag>1&&a[flag-1]>maxx_need){
                    del=flag-1;
                    vis[a[del]]=0;
                }
                else{
                    ll minn_need=inf;
                    for(int i=1;i<=n;i++){
                        if(!vis[i]){
                            minn_need=i;
                            break;
                        }
                    }
                    ll minn_back=0;
                    for(int i=flag+1;i<=n;i++){
                        if(a[i]!=0&&a[i]<a[minn_back])minn_back=i;
                    }
                    if(minn_need>a[minn_back]){
                        del=minn_back;
                        vis[a[del]]=0;
                    }
                    else{
                        nomin=1;
                        for(int i=1;i<=n;i++){
                            if(!vis[i])b[++k]=i;
                        }
                        for(int i=flag,j=1;i<=n;i++){
                            if(aa[i]==0){
                                aa[i]=b[j++];
                            }
                        }
                        for(int i=2;i<=n;i++){
                            if(aa[i]<aa[i-1]){
                                del=i-1;
                                vis[aa[del]]=0;
                                break;
                            }
                        }
                        memset(b,0,sizeof b);
                        k=0;
                    }
                }
            }
            for(int i=1;i<=n;i++){
                if(!vis[i])b[++k]=i;
            }
            for(int i=flag,j=1;i<=n;i++){
                if(a[i]==0&&i!=del){
                    a[i]=b[j++];
                }
            }
            if(nomin){
                for(int i=2;i<=n;i++){
                    if(a[i]<a[i-1]){
                        del=i-1;
                        vis[a[del]]=0;
                        break;
                    }
                }
            }
        }
        if(del==-1)del=n;
        for(int i=1;i<=n;i++){
            if(i!=del)cout<<a[i]<<' ';
        }
        cout<<'\n';
    }
    return 0;
}

T3.T4.

到现在没有整明白,就忽略掉它们吧。

四、总结

再接再励,争取省一。

本章完...

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值