ICode9

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

Educational Codeforces Round 102 (Rated for Div. 2)(A-E)

2021-01-18 09:35:21  阅读:200  来源: 互联网

标签:f1 Educational Rated cin int Codeforces f2 ne dis


目录

A. Replacing Elements

大意:

给出n个数,以及一个数d,可以对这n个数进行任意次操作,每次操作可以选互不相同的三个值i j k,然后令\(a_i=a_j+a_k\)

问能否在任意次操作后,使得每个数都小于等于d

思路:

先看是不是都小于等于d,如果都小于等于d直接输出yes

否则的话,看是否能找到两个数的和小于等于d,能找到的话就可以把大于d的数都赋值为这两个数的和

#include <bits/stdc++.h>

using namespace std;

const int N = 1e2 + 5;
typedef long long LL;
int t, a[N];
int main() {
    cin >> t;
    while (t--) {
        int n, d, flag = 0;
        cin >> n >> d;
        for (int i = 0; i < n; i++) {
            cin >> a[i];
            if (a[i] > d) flag = 1;
        }
        if (flag) {
            int yes = 0;
            for (int i = 0; i < n; i++) {
                for (int j = i + 1; j < n; j++) {
                    if (a[i] + a[j] <= d) yes = 1;
                }
            }
            if (yes) cout << "YES" << endl;
            else
                cout << "NO" << endl;
        } else
            cout << "YES" << \endl;
    }
    return 0;
}

B. String LCM

大意:

求两个字符串的lcm,字符串的lcm定义为能被两个字符串整除的最短字符串,若a由1一个或多个b拼接而成,那么称a能被b整除

如果找不到lcm,输出-1

思路:

直接求两个字符串长度的lcm,然后将他们都拼接到这个长度上来,最后看是否相等,相等的话就直接输出,否则没有lcm

#include <bits/stdc++.h>

using namespace std;

typedef long long LL;
typedef pair<int, int> PII;
int const N = 2e5 + 10;
int n, m, T;

int main() {
    cin >> T;
    string s1, s2;
    while (T--) {
        cin >> s1 >> s2;
        int l1 = s1.size();
        int l2 = s2.size();
        int len = l1 * l2 / __gcd(l1, l2);
        string ans1 = "";
        for (int i = 0; i < len/l1;i++){
            ans1 += s1;
        } 
        string ans2 = "";
        for (int i = 0; i < len/l2;i++){
            ans2 += s2;
        } 

        if (ans1 == ans2) cout << ans1 << endl;
        else
            cout << "-1" << endl;

        
    }
    return 0;
}

C. No More Inversions

大意:

给出n和k,a为一个序列:\(1, 2, 3, \dots, k - 1, k, k - 1, k - 2, \dots, k - (n - k)\)

要求求出一个1到k的全排列p,使得\(b[i] = p[a[i]]\),此时b的逆序对数量不小于a,且b的字典序最大

思路:

一顿乱搞,因为a的后面\(2(k - (n - k))+1\)个数是对称的,那么构造出来的b后面的数也是对称的,然后既要满足b的逆序对数量不小于a,又要满足b的字典序最大,所以在纸上试试发现只能是前面的数保持不变,然后后面的“V"字上下颠倒过来即可

#include <bits/stdc++.h>

using namespace std;

const int N = 1e6 + 5;
typedef long long LL;
int t, n, k;
int main() {
    cin >> t;
    while (t--) {
        cin >> n >> k;
        for (int i = 1; i < (k - (n - k)); i++) {
            cout << i << ' ';
        }
        for (int i = k; i >= (k - (n - k)) ; i--) {
            cout << i << ' ';
        }
        cout << endl;
    }
    return 0;
}

D. Program

大意:

一个机器人,给出长度为n的指令,’+‘代表向前走1步,'-'代表向后退一步,初始位置为0

现在给出m个查询,每个查询给出l和r

要求问在忽略l到r这一段指令的情况下,机器人坐标的取值范围有多大

思路:

前缀后缀去做,首先求出前缀数组,那么就代表在第i步机器人的坐标为\(pre[i]\)

同时在求前缀的时候维护一个\(maxp[i]\)代表机器人在前i步,从0开始能达到的最右边的位置

维护一个\(minp[i]\)代表机器人在前i步,从0开始能达到的最左边的位置

然后求后缀,\(bk[i]\),在求后缀的时候更新\(maxb[i]\)和\(minb[i]\),分别代表从i到n这个区间,与终点的左右偏移量最大是多少

最后分别求出来起点和终点的左右偏移量,然后取个max相减即可

#include <bits/stdc++.h>

using namespace std;

const int N = 2e5 + 5;
typedef long long LL;
int t, pre[N],maxp[N],minp[N],maxb[N],minb[N],bk[N];
string s;
int main() {
    cin >> t;
    while (t--) {
        int n, m;
        cin >> n >> m;
        cin >> s;
        s =" "+ s;
        maxp[0] = maxb[n + 1] = 0;  //-0x3f3f3f3f;
        minp[0] = minb[n + 1] = 0;  //0x3f3f3f3f;
        pre[0] = pre[n+1] = bk[n + 1] = bk[0] = 0;
        for (int i = 1; i <= n; i++) {
            if (s[i] == '+')
                pre[i] = pre[i - 1] + 1;
            else
                pre[i] = pre[i - 1] - 1;
            maxp[i] = max(maxp[i - 1], pre[i]);
            minp[i] = min(minp[i - 1], pre[i]);
        }
        for (int i = n; i >=0 ; i--) {
            if (s[i] == '+')
                bk[i] = bk[i + 1] + 1;
            else
                bk[i] = bk[i + 1] - 1;
            maxb[i] = max(maxb[i + 1], bk[i]);
            minb[i] = min(minb[i + 1], bk[i]);
        }
        while(m--){
            int l, r;
            cin >> l >> r;
            int max1 = maxp[l - 1], min1 = minp[l - 1];
            int mid = pre[r] - pre[l - 1];
            r++;
            int max2 = pre[n] - mid - minb[r], min2 = pre[n] - mid - maxb[r];
            //cout <<pre[n]<<' '<< max1 << ' ' << min1 << ' ' << max2 << ' ' << min2 << endl;
            cout << max(max1, max2) - min(min1, min2) + 1 << endl;
        }
    }
    return 0;
}

E. Minimum Path

大意:

定义无向图上两个点之间的距离为两点之间路径之和减去最大边权,再加上最小边权

输出1号点到其他所有点的最短距离

思路:

相当于在最短路的基础上加了两个约束条件,一个约束条件是必须有一条边的权被减去,一个约束条件是必须有一条边的权被加了一次

那么可以开三维数组:\(dis[i][f1][f2]\)代表1号点到i号点,约束条件1和2是否达到的最短路径

这样只需要将dijstra进行修改,每次更新都有四个选择:这条边作为普通的边,这条边作为最大边,这条边最为最小边,以及这条边既是最大又是最小边

证明正确性:因为全部的情况都被枚举出来,而对于一条路来说,如果必须要删掉一条边,然后加上一条边,那么一定是删掉最大边,加上最小边,所以\(dis[i][1][1]\)一定是符合条件的最小值

#include <bits/stdc++.h>

using namespace std;

typedef pair<int, int> PII;
int const N = 4e5 + 10;
int e[N], ne[N], h[N], idx, n, m, st[N][2][2];
typedef long long LL;
LL dis[N][2][2], w[N];

void add(int a, int b, int c) {
    e[idx] = b, w[idx] = c, ne[idx] = h[a],
    h[a] = idx++;  // e代表idx连接的边,w为权,ne代表idx的上一条边,h代表a最近加入的一条边
}
struct node {
    int ver, f1, f2;
    LL dis;
    bool operator<(const node& a) const { return dis > a.dis; }
};
// 堆优化版dijkstra
void dijkstra() {
    memset(dis, 0x3f, sizeof dis);  // 初始化距离为无穷
    priority_queue<node>q;  // 定义一个按照距离从小到大排序的优先队列,第一维:距离,第二维:点
    dis[1][0][0] = 0;  // 一开始源点距离为0
    node start;
    start.dis = 0, start.ver = 1, start.f1 = start.f2 = 0;
    q.push(start);      // 把源点信息放入队列
    while (q.size()) {  // 每个点只出入队列一次
        auto t = q.top();
        q.pop();

        LL distance = t.dis;
        int ver = t.ver, f1 = t.f1, f2 = t.f2;
        if (st[ver][f1][f2])
            continue;  // 这个操作保证每个点只出入队一次,因为队列里面可能会出现{dis1[3],
                       // 3}, {dis2[3],
                       // 3}的情况,这样保证dis1[3]<dis2[3]时,3号点只进出入队一次
        st[ver][f1][f2] =1;  // 标记,因为dijkstra的贪心策略保证每个点只需要进出队一次

        for (int i = h[ver]; ~i; i = ne[i]) {  // 遍历ver的邻接点
            int j = e[i];
            if (dis[j][f1][f2] > distance + w[i]) {
                dis[j][f1][f2]  = distance + w[i];
                node ne;
                ne.dis = dis[j][f1][f2],ne.f1 = f1,ne.f2=f2,ne.ver=j;
                q.push(ne); 
            }

            if (f1 == 0) {
                if (dis[j][1][f2] > distance) {
                    dis[j][1][f2]  = distance ;
                    node ne;
                    ne.dis = dis[j][1][f2],ne.f1 = 1,ne.f2=f2,ne.ver=j;
                    q.push(ne); 
                }
            }
            if (f2 == 0) {
                if (dis[j][f1][1] > distance + 2*w[i]) {
                    dis[j][f1][1]  = distance + 2*w[i];
                    node ne;
                    ne.dis = dis[j][f1][1],ne.f1 = f1,ne.f2=1,ne.ver=j;
                    q.push(ne);  
                }
            }
            if (f1 == 0&&f2==0) {
                if (dis[j][1][1] > distance + w[i]) {
                    dis[j][1][1]  = distance + w[i];
                    node ne;
                    ne.dis = dis[j][1][1] ,ne.f1 = 1,ne.f2=1,ne.ver=j;
                    q.push(ne);  // 这里不需要判断st,因为一旦更新发现更小必须放入队列
                }
            }
        }
    }
}

int main() {
    cin >> n >> m;
    memset(h, -1, sizeof h);
    for (int i = 1, a, b, c; i <= m; ++i) {  // 读入m条边
        scanf("%d%d%d", &a, &b, &c);
        add(a, b, c);
        add(b, a, c);
    }
    dijkstra();
    for (int i = 2; i <= n; i++) cout << dis[i][1][1] << ' ';
    return 0;
}

标签:f1,Educational,Rated,cin,int,Codeforces,f2,ne,dis
来源: https://www.cnblogs.com/dyhaohaoxuexi/p/14291218.html

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

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

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

ICode9版权所有