ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

牛客小白月赛54

2022-08-12 22:31:09  阅读:157  来源: 互联网

标签:ch end int 54 back long 牛客 小白月赛 push


牛客小白月赛54

https://ac.nowcoder.com/acm/contest/38457#question
题意不用说,因为是中文,自己看就得了
感觉这次比上回难点

EF 待补

A - Sum

最容易想到的思路就是拿个堆,每次找最大的两个数相加。但是这么做复杂度暴了(我不会算)。
考虑优化一下。先排个序,每次贪心的选最大的两个相加(为什么是两个呢,因为少的肯定比多的优,先加的比较少的话,就可以再多加几次)。这个过程就相当于从后往前求和,前缀和优化一下就行(后缀和也行,更方便)。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int mod = 1e7 + 7, N = 2e5 + 5;
ll a[N], sum[N];

void solve () {
    int n;
    ll ans = 0;
    scanf ("%d", &n);
    for (int i = 1; i <= n; i ++)    cin >> a[i];
    sort (a + 1, a + n + 1);
    for (int i = 1; i <= n; i ++)    sum[i] = sum[i-1] + a[i];
    
    for (int i = 1; i < n; i ++) {
        ll dx = sum[n] - sum[n-i-1];
        if (dx < 0)     break;
        ans += dx;
    }
    
    cout << max(0ll, ans % mod) << endl;
}

int main () {
    int t;
    cin >> t;
    while (t --) {
        solve ();
    }
}

B - Gaming

题目要求在不取满 \(m\) 个的情况下尽可能大,易得最优可能是取 \(m-1\) 个
容易想到的思路就是枚举那个不选的点,然后比较选取权值最小的去掉。
如图:

权值的计算涉及区间覆盖,可以利用差分来做

#include <bits/stdc++.h>
#define int long long

using namespace std;
const int N = 1e6 + 5;
int n, m, sum[N];

signed main () {
    cin >> n >> m;
    int ans = 0, tot = 0;
    for (int i = 1; i <= n; i++) {
        int l, r, s;
        cin >> l >> r >> s;
        sum[r+1] -= s, sum[l] += s;
        tot += s;
    }

    for (int i = 1; i <= m; i ++) {
        sum[i] += sum[i-1];
        //cout << sum[i] << ' ';
        ans = max (ans, tot - sum[i]);
    }

    cout << ans << endl;
}


//不取某点,枚举该点

C - School

可以先把时间转化为具体的值(统一化单位为 分),然后问题就变为,有 \(n\) 个区间,\(m\) 次询问某点是否在区间内。对于 \(n\) 个区间可以先进行排序,合并等处理,然后二分查找,时间复杂度就可以由 \(O(nq)\) 变为 \(O(qlogn)\)
要读入优化,不然会超时
注意如果输入的左端点大于右端点就代表跨了 天 ,故要划分为两个区间

#include <bits/stdc++.h>
#define int long long

using namespace std;
typedef pair<int, int> pii;
const int N = 1e3 + 5, M = 2e6 + 5;
int n, m, h, q;
vector <int> l, r;

inline int read()
{
	 int x=0,f=1; char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9')x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
	return x*f;
}

signed main () {
    n = read(), h = read(), m = read(), q = read();
    int maxn = h*m;
    for (int i = 0; i < n; i ++) {
        int a, b, c, d;
        a = read(), b = read(), c = read(), d = read();
        a = a*m + b, c = c*m + d;   
        if (a > c) {
            l.push_back (a), r.push_back (maxn);
            l.push_back (0), r.push_back (c);
        }
        else    l.push_back(a), r.push_back(c);
    }
    
    sort (l.begin(), l.end()), sort (r.begin(), r.end());
    l.erase (unique(l.begin(), l.end()), l.end());
    r.erase (unique(r.begin(), r.end()), r.end());

    int sz = l.size();
    // for (int i = 0; i < sz; i ++)
    //     cout << l[i] << ' ' << r[i] << endl;

    while (q --) {
        int x, y;
        x = read(), y = read();
        x = x*m + y;
        //cout << x << " ";
        int j = lower_bound (r.begin(), r.end(), x) - r.begin();
        //cout << j << endl;
        if (j == sz)    printf("Yes\n");
        else {
            if (l[j] <= x || r[j] == x)     printf("No\n");
            else    printf("Yes\n");
        }
    }
}


//O(qlogn)

D - Word

可以把每一个单词都看成一个点,两点之间能连边的条件为有且仅有一个字符不同。那么就可以按照这个思路去构造图,然后跑最短路即可。
注意路径记录(有人不会QAQ)

#include <bits/stdc++.h>

using namespace std;
typedef pair<int, int> pii;
const int N = 2005;
int n, m, dis[N], path[N];
string s[N];
bool vis[N];
int a[N][N];

bool match (string a, string b) {
    int dif = 0;
    for (int i = 0; i < m; i ++)
        if (a[i] != b[i])   dif ++;
    if (dif == 1)   return true;
    return false;
}

int dijkstra () {
    for (int i = 0; i <= n; i ++) {
        dis[i] = a[0][i];
        vis[i] = false;
        path[i] = -1;
    }
    vis[0] = true;
    dis[0] = 0;
    for (int i = 0; i <= n; i ++) {
        int p, minn = 0x3f3f3f3f;
        for (int j = 0; j <= n; j ++) {
            if (!vis[j] && dis[j] < minn) {
                p = j;
                minn = dis[j];
            }
        }

        vis[p] = true;
        for (int j = 0; j <= n; j++) {
            if (dis[p] + a[p][j] < dis[j]) {
                dis[j] = minn + a[p][j];
                path[j] = p;
            }
        }
    }

    if (dis[n] == 0x3f3f3f3f)
        return -1;
    return dis[n]-1;
}

void print () {
    stack<int> q;
    int j = n;
    while (path[j] != -1) {
        q.push(j), j = path[j];
    }
    q.push (j);
    cout << s[0] << endl;
    while (!q.empty()) {
        cout << s[q.top()] << endl;
        q.pop();
    }
}

int main () {
    memset (a, 0x3f, sizeof a);
    memset (path, -1, sizeof path);
    cin >> n >> m;
    for (int i = 1; i <= n; i ++)   cin >> s[i];
    n ++;
    cin >> s[0] >> s[n];

    if (s[0] == s[n]) {
        cout << 0 << endl;
        cout << s[0] << endl << s[n] << endl;
        return 0;
    }
    
    for (int i = 0; i <= n; i ++) {
        a[i][i] = 0;
        for (int j = i + 1; j <= n; j++) {
            if (s[i] != s[j] && match(s[i], s[j]))
                a[i][j] = a[j][i] = 1;
        }
    }

    int t = dijkstra ();
    cout << t << endl;
    if (t != -1) {
        print();
    }
        
}

//图论
//能转化的建一条边,跑最短路

E - Slash

F - Traveling

标签:ch,end,int,54,back,long,牛客,小白月赛,push
来源: https://www.cnblogs.com/CTing/p/16581524.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有