5.28SDNU训练赛 简短题解

VJ 交题交不上 ,给大家造成谅解,敬请原谅

相信以后会越来越好的 , 一起努力 。。。

 

A.   签到题

注意

freopen("input.txt", "r", stdin);

freopen("output.txt", "w", stdout);

排序输出Index 即可

代码 The__Flash

#include <set>
#include <map>
#include <ctime>
#include <queue>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define eps 1e-6
#define pi acos(-1.0)
#define ll long long int
using namespace std;

struct node
{
    int data;
    int id;
}a[1000 + 5];

bool cmp(node a, node b)
{
    return a.data > b.data;
}

int main()
{
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    int n, m;
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= n; ++i)
    {
        scanf("%d", &a[i].data);
        a[i].id = i;
    }
    sort(a + 1, a + n + 1, cmp);
    printf("%d\n", a[m]);
    for(int i = m; i >= 1; --i)
        printf("%d%c", a[i].id, i == 1 ? '\n' : ' ');
    fclose(stdin);
    fclose(stdout);
    return 0;
}

B. dp 题   并查集分组之后,按分组背包的方式递推

代码  breakagain 

#include <algorithm>
#include <iostream>
#include <string>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>

using namespace std;

const int mod = 332748118;
const int maxn = 3e3 + 5;
typedef long long ll;

int fa[maxn], v[maxn], c[maxn], dp[maxn];
vector <int> a[maxn];

int Find(int x)
{
    while(x != fa[x])
        x = fa[x] = fa[fa[x]];
    return x;
}

void Union(int x, int y)
{
    int fx = Find(x), fy = Find(y);
    if(fx != fy)
        fa[fx] = fy;
}

int main()
{
    int n, m, w;
    cin >> n >> m >> w;
    for(int i = 1; i <= n; ++i)
        fa[i] = i;
    for(int i = 1; i <= n; ++i)
        cin >> c[i];
    for(int i = 1; i <= n; ++i)
        cin >> v[i];
    for(int i = 0; i < m; ++i)
    {
        int x, y;
        cin >> x >> y;
        Union(x, y);
    }
    for(int i = 1; i <= n; ++i)
    {
        a[Find(i)].push_back(i);
    }
    int tn = n;
    for(int i = 1; i <= n; ++i)
    {
        if(a[i].size() == 0)
            continue;
        int cc = 0, vv = 0;
        int lim = a[i].size();
        for(int j = 0; j < lim; ++j)
        {
            cc += c[a[i][j]];
            vv += v[a[i][j]];
        }
        c[++tn] = cc;
        v[tn] = vv;
        a[i].push_back(tn);
    }
    for(int k = 1; k <= n; ++k)
    {
        if(a[k].size() == 0)
            continue;
        for(int j = w; j >= 0; --j)
        {
            for(int i = 0; i < a[k].size(); ++i)
            {
                if(j >= c[a[k][i]])
                {
                    dp[j] = max(dp[j], dp[j-c[a[k][i]]] + v[a[k][i]]);
                }
            }
        }
    }
    cout << dp[w] << endl;
}

#ifdef OJ
freopen("D:\\decug\\test.in", "r", stdin);
freopen("D:\\decug\\test.out", "w", stdout);
#endif // OJ

我的长长的代码

#include<bits/stdc++.h>
using namespace std;
#define maxn (1000 + 100)
#define up(i,x,y) for(ll i=x;i<=y;i++)
#define down(i,x,y) for(ll i=x;i>=y;i--)
#define bug cout<<"-----------"<<endl
#define pb push_back
typedef long long ll;

ll w[ maxn * 2 ],b[ maxn * 2];

vector<ll>V [ 1000 + 10 ];
vector<ll> tmp_V[ 1000 + 10];

ll f[ maxn ];
ll belong[ maxn ];

ll findd(ll x)
{
    if(f[x] == x)return f[x];

    return f[x] = findd( f[x] );

}



ll dp [ maxn ] [ maxn ];

int main()
{
    ll n, m ,W ; scanf("%lld %lld %lld",&n,&m,&W);

    up(i,1,n)scanf("%lld",&w[i]);

    up(i,1,n)scanf("%lld",&b[i]);


    up(i,1,n)f[i] = i;
    ll cnt = 0 ;

    up(i,1,m)
    {
        ll x, y ;scanf("%lld %lld",&x,&y);

        ll a = findd(x) , b = findd(y);

        if(a < b)
        {
            f[ b ] = a;
        }
        else if( b < a)
        {
            f[ a ] = b;
        }
    }


    up(i,1,n)
    {
        if(f[i] == i)
        {
            ++cnt;
            V[cnt].pb(i);
            belong[ i ] = cnt;
        }
        else
        {
            ll a = findd(i);
            V[ belong[ a ] ] .pb(i);

            belong[i] =  belong[a];
        }
    }


//    cout << cnt << endl;
//    up(i,1,cnt)
//    {
//        cout << i <<" : ";
//
//        for(ll c : V[i])
//            cout << c <<' ';
//        cout << endl;
//    }

    ll res = 0;

    up(i,1,cnt)
    {
        ll sum = 0;
        ll Weight = 0;

        up(j,0,V[i].size() - 1)
        {
            sum += b [ V[i][j] ] ;

            Weight += w [ V[i][j] ] ;

        }

//        if(Weight <= W)
//        {
//
//            res = max(sum , res);
//        }
        if(V[i].size() > 1)
        {
            b[++n] = sum;
            w[ n ] = Weight;
            tmp_V[i].pb(n);

        }


    }

    up(i,1,cnt)
    {
        if(V[i].size() > 1)
        {
            V[i].pb( tmp_V[i] [0] );
        }
    }


//    cout << res << endl;


    up(i,1,cnt)
    {
        up(j,0, V[i].size()-1)
        {

            ll cur = V[i][j];  当前物品的 Index

            down(k, W ,0)
            {

                dp[ i + 1 ][ k ] = max(dp[i + 1][ k ] , dp[ i ][k]);

                if( k + w[cur] <= W)

                {

                    dp[i + 1][ k + w[ cur ] ] = max( dp[i + 1][ k + w[ cur ] ] ,
                                                dp[i][k] + b[ cur ] );

                }

            }

        }


    }


//    up(i,1,cnt +  1)
//    {
//
//        up(j,0,W)
//        {
//            cout << dp[i][ j ] << ' ';
//        }
//        cout << endl;
//
//
//    }
//    up(i,0,W)
//        res = max(res, dp[ cnt + 1 ][ i ]);


    cout << dp[cnt+1][W] <<endl;





}
/*
10 5 100
70 67 8 64 28 82 18 61 82 7
596434 595982 237932 275698 361351 850374 936914 877996 789231 331012
1 7
2 4
3 6
5 7
1 5
*/
// 22200

C.构造题         以前有这种题    给你钱数n,和 m 个纸币的面值,问你有多少种方式能够凑出钱数n ?

现在给你总的方式数,让你构造 n , m  和 m 个 纸币的面值

考虑 只有两种面值  1 and  2    ,对于某一个 n ,先求最少的 纸币数  贪2 在贪 1 

总方式数  为 1 + 这时候 2 的个数 (因为2可以换为1)

代码  Thankyou 

#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <cstdio>
#include <iostream>
#include <algorithm>
using namespace std;

int main()
{
    int n;
    cin >> n;
//    if(n == 1)
//        cout << "1\n1 1\n1\n";
//    else
//    {
//        cout << 2 * (n - 1);
//        cout << " 2\n1 2\n";
//    }
    if(n == 1)
        cout << '1' << ' ' << '1' << '\n' << '1' << '\n';
    else
        cout << 2 * (n - 1) << ' ' << '2' << '\n' << '1' << ' ' << '2' << '\n';
    return 0;
}

 D.  构造矩阵   使其 每行每列 两个对角线的  和 都为 奇数

n 为 odd

令 c =  n / 2 + 1 , 先让第c行添上奇数,第c列填上奇数

再让剩下的奇数(4 的倍数 )按中心点(c,c) 对称分布 

剩下的填even即可

#include<bits/stdc++.h>
using namespace std;
#define maxn (int)1e5+1000
#define up(i,x,y) for(int i=x;i<=y;i++)
#define down(i,x,y) for(int i=x;i>=y;i--)
#define bug cout<<"-----------"<<endl
#define pb push_back
typedef long long ll;


   n * n
   n * n / 2 +  1 - n
//3 * 3 - 3
int rec[100 + 10][100 + 10];
int main()
{
    int n; cin >> n;
    vector<int>V1,V2;
    up(i,1,n*n)
    {
        if( i % 2 == 1)
        {

            V1.pb(i);
        }
        else
            V2.pb(i);

    }

    int c = n / 2 + 1;


    int cnt1 = 0,cnt2 = 0;
    up(i,1,n)
    {
        rec[i][c] = V1[cnt1++];
    }

    up(i,1,n)
    {
        if(i == c)continue;
        rec[c][i] = V1[cnt1++];

    }


    c -= 1;

    up(i,1,c)
    {
        up(j,1,c)
        {
            if(cnt1 == V1.size())
                break;

            rec[i][j] = V1[cnt1++];

            rec[i][n+1-j] = V1[cnt1++];

            rec[n+1-i][j] = V1[cnt1++];

            rec[n+1-i][n+1-j] = V1[cnt1++];


        }
    }

    up(i,1,n)
    {
        up(j,1,n)
        {
            if(rec[i][j] == 0)
            {
                rec[i][j] = V2[cnt2++];
            }

        }
    }

    up(i,1,n)up(j,1,n)
    {
        printf("%d%c",rec[i][j],j == n?'\n':' ');
    }


}

代码 

2018muyu 

#include<iostream>
#include<cstdio>
using namespace std;
int a[55][55];
int n;
int main()
{

    scanf("%d",&n);
    int m=n*n/2+1;
    for(int i=1;i<=n;i++)
    {
        a[i][n/2+1]=1;
        a[n/2+1][i]=1;
    }
    m-=n+n-1;
    int x=1,y=1;
    while(m)
    {
        a[x][y]=1,a[n-x+1][y]=1;
        a[x][n-y+1]=1,a[n-x+1][n-y+1]=1;
        m-=4;
        if(a[x][y+1]==0&&y+1<=n/2)
        {
            y=y+1;
        }
        else if(y==n/2)
        {
            x=x+1,y=1;
        }
    }
    int cnt1=1,cnt2=2;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=n;j++)
        {
            if(a[i][j]==1)
            {
                a[i][j]=cnt1;
                cnt1+=2;
            }
            else if(a[i][j]==0)
            {
                a[i][j]=cnt2;
                cnt2+=2;
            }
            cout<<a[i][j]<<" ";
        }
        cout<<endl;
    }
}

E:  矩阵内的合并 ,增量为矩阵中的最大值

贪心即可

代码 lanzongwei 

/*********************************************************
Flie Name: e.cpp
Author: Liupo
Email: lanzongwei541@gmail.com
Creat time: 2019年05月28日 星期二 19时51分27秒
*********************************************************/
#include<bits/stdc++.h>
using namespace std;

using ll = long long;

priority_queue<ll>pre;

int main(){
	ll n;
	scanf("%lld", &n);
	for(auto i = 0; i < n; i++){
		ll tem;
		scanf("%lld", &tem);
		pre.push(tem);
	}
	ll tt = 0, aim = 0;
	ll now = 0, ans = 0;
	while(!pre.empty()){
		while(tt != 1 << (2 * aim)){
			now += pre.top();
			pre.pop();
			tt++;
		}
		ans += now;
		aim++;
	}
	printf("%I64d\n", ans);
    
    return 0;
}

F.   判断此时的图是哪一种图

按点的度数直接特判即可

#include<bits/stdc++.h>
using namespace std;
#define maxn (int)1e5+1000
#define up(i,x,y) for(int i=x;i<=y;i++)
#define down(i,x,y) for(int i=x;i>=y;i--)
#define bug cout<<"-----------"<<endl
#define pb push_back
typedef long long ll;

int indeg[ maxn ];
int main()
{
    int n , m;  cin >> n >> m;

    up(i,1,m)
    {
        int x,y; scanf("%d %d",&x,&y);
        indeg[x] ++;
        indeg[y] ++;
    }


//    up(i,1,n)
//    {
//        cout << indeg[i] <<' ';
//    }
//    cout << endl;


    bool f = 0;


    up(i,1,n)
    {
        if(indeg[i] != 2)
            f = 1;
    }

    if(f == 0)
    {
        printf("ring topology\n");
        return 0;
    }


    vector<int>indeg_1,indeg_n;
    up(i,1,n)
    {
        if(indeg[i] == 1)
        {
            indeg_1.pb(i);
        }
        else if(indeg[i] == n-1)
        {
            indeg_n.pb(i);
        }
    }

    if(indeg_1.size() == n - 1 && indeg_n.size() == 1)
    {
        printf("star topology\n");
        return 0;
    }


    indeg_1.clear();
    vector<int>indeg_2;
    up(i,1,n)
    {
        if(indeg[i] == 1)
        {
            indeg_1.pb(i);
        }
        else if(indeg[i] == 2)
        {
            indeg_2.pb(i);
        }
    }

    if(indeg_1.size() == 2 && indeg_2.size() == n - 2)
    {
        printf("bus topology\n");
        return 0;

    }

    printf("unknown topology\n");


}

G.  判断 此时的题目最早完成的时刻,跟你能提交的时间段

一直做,等到最后一次能提交时提交即可

代码  ignb 

#include<stdio.h>
#include<iostream>
#include<map>
#include<algorithm>
#include<cstring>
#include<string.h>
#include<string>
#include<math.h>
#include<vector>
#include<map>
using namespace std;
typedef long long ll;
#define MAXN 10005
#define INF 0x3f3f3f3f//将近int类型最大数的一半,而且乘2不会爆int
const ll MOD = 332748118;

int a[MAXN];
struct student
{
    int a, b;
} stu[MAXN];

int cmp(student x, student y)
{
    return x.a < y.a;
}
int main()
{
    int n, m, sum=0;
    cin >> n;
    for(int i=0; i<n; ++i)
    {
        scanf("%d", &a[i]);
        sum+=a[i];
    }
    cin >> m;
    for(int i=0; i<m; ++i)
    {
        scanf("%d %d", &stu[i].a, &stu[i].b);
    }
    sort(stu, stu+n, cmp);
    int flag=1;
    for(int i=0; i<n; ++i)
    {
        if((stu[i].a < sum && stu[i].b > sum) || sum < stu[i].a)
        {
            flag=0;
            cout << stu[i].a << '\n';
            break;
        }
        if(stu[i].a == sum || stu[i].b == sum)
        {
            flag=0;
            cout << sum << '\n';
            break;
        }
    }
    if(flag) puts("-1");
    return 0;
}

H题  双指针 直接for循环即可

代码 18yanmingfu 

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int N = 1e5 + 5;
typedef pair<int, int> P;
P a[N];
int c[N], t[N];
int f[N];

int s(int x,int low, int high){
    int mid = (low + high) / 2;
    int u = a[mid].first;
    int v = a[mid].second;
    if (x > u && x <= v)
        return mid;
    if (x <= u)
        s(x, low, mid - 1);
    else
        s(x, mid + 1, high);
}
int main(){
    ios::sync_with_stdio(0);
    int n, m, x, ans;
    cin >> n >> m;
    int st = 0;
    for (int i = 1; i <= n; i++){
        cin >> c[i] >> t[i];
        a[i] = P(st, st + c[i] * t[i]);
        st += c[i] * t[i];
    }
    for (int i = 0; i < m; i++){
        cin >> x;
        ans = s(x, 1, n);
        cout << ans << "\n";
    }


    return 0;
}

愿所有的努力不被辜负!!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值