Educational Codeforces Round 102 (Rated for Div. 2)(A~D)

A. Replacing Elements(水贪心)

题意

思路

  1. 经过合理操作之后的数都小于等于 d,有两种情况可以:
    1. 本身数列所有的元素的都小于等于 d,这个时候不需要操作。。
    2. 数列中最小的两个数之和小于等于 d

代码

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <string>
#include <string>
#include <map>
#include <bitset>
#include <vector>
void fre() { system("clear"), freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { system("clear"), freopen("A.txt", "r", stdin);}
void Run(int x = 0) {     
#ifdef ACM  //宏定义免注释 freopen
    if(! x) fre(); else Fre();
#endif
}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define db double
#define ll long long
#define ull unsigned long long
#define Pir pair<ll, ll>
#define m_p make_pair
#define for_(i, s, e) for(ll i = (ll)(s); i <= (ll)(e); i ++)
#define rep_(i, e, s) for(ll i = (ll)(e); i >= (ll)(s); i --)
#define memset(a, b, c) memset(a, (int)b, c);
#define size() size() * 1LL
#define sc scanf
#define pr printf
#define sd(a) scanf("%lld", &a)
#define ss(a) scanf("%s", a)
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define esp 1e-7
#define mod (ll)(1e9 + 7)
using namespace std;
/*=========================ACMer===========================*/
const ll mxn = 2e5 + 10;
ll ar[mxn];


int main()
{
    Run();
    ll T; sd(T);
    while(T --)
    {
        ll n, d;
        sc("%lld %lld", &n, &d);
        for_(i, 1, n) sd(ar[i]);
        sort(ar + 1, ar + 1 + n);
        if(ar[1] + ar[2] <= d || ar[n] <= d)
            pr("YES\n");
        else
            pr("NO\n");
    }




    return 0;
}

B. String LCM(思路)

题意

  1. 给两个仅由’a’、‘b’ 字符组成的字符串 u、v,问能不能找出一个最短的字符串 w,使 w 可以同时分别整除 u、v,
  2. 定义字符串乘法:字符串 x 数字 ,例如:abc x 2 = abcabc、ab x 3 = ababab
  3. 字符串 x 整除 y 的意思是:存在一个整数 c,使得 y * c = x。
  4. 如果存在输出最段的 w,否则输出 - 1。

思路

  1. 我们考虑如果存在一个 w 字符串,能同时整除 u、v 字符串,
    1. w 能整除 u,那么 w 的长度是 u 长度的倍数,
    2. w 能整除 v,那么 w 的长度是 v 长度的倍数,
  2. 所有 w 的长度是 u、v 长度的最小公倍数,这里设 u、v、w 的长度为 | u|、|v|、|w|,那么$|w| = Lcm(|u|, |v|)$,
  3. 这个时候我们让我们
    1. u ′ = u ∗ ∣ w ∣ / ∣ u ∣ u'=u*|w|/|u| u=uw/u
    2. v ′ = v ∗ ∣ w ∣ / ∣ v ∣ v'=v*|w|/|v| v=vw/v
  4. 最后判读如果 u ′ = = v ′ u'==v' u==v 的话,那么我们要求的 w 就是 u’或 v’,
  5. 否则输出 - 1。

代码

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <string>
#include <string>
#include <map>
#include <bitset>
#include <vector>
void fre() { system("clear"), freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { system("clear"), freopen("A.txt", "r", stdin);}
void Run(int x = 0) {     
#ifdef ACM  //宏定义免注释 freopen
    if(! x) fre(); else Fre();
#endif
}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define db double
#define ll long long
#define ull unsigned long long
#define Pir pair<ll, ll>
#define m_p make_pair
#define for_(i, s, e) for(ll i = (ll)(s); i <= (ll)(e); i ++)
#define rep_(i, e, s) for(ll i = (ll)(e); i >= (ll)(s); i --)
#define memset(a, b, c) memset(a, (int)b, c);
#define size() size() * 1LL
#define sc scanf
#define pr printf
#define sd(a) scanf("%lld", &a)
#define ss(a) scanf("%s", a)
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define esp 1e-7
#define mod (ll)(1e9 + 7)
using namespace std;
/*=========================ACMer===========================*/
const ll mxn = 2e5 + 10;
ll ar[mxn];
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }
ll lcm(ll a, ll b) { return a * b / gcd(a, b); }


int main()
{
    Run();
    ll T; sd(T);
    while(T --)
    {
        string a, b;
        cin >> a >> b;
        if(a.size() < b.size())
        {
            string t = a;
            a = b;
            b = t;
        }

        ll la = a.size();
        ll lb = b.size();
        ll n = lcm(la, lb);
        string ta ="";
        string tb ="";
        for_(i, 1, n / la) ta += a;
        for_(j, 1, n / lb) tb += b;
        if(ta == tb)
        {
            cout << ta << endl;
        }
        else
            pr("-1\n");
    }




    return 0;
}



C. No More Inversions(规律构造)

题意

  1. 给我们一个两个变量 n 、 k ( k < = n < 2 ∗ k ) n、k(k<=n<2*k) nkk<=n<2k, 注意这两个变量的取值限制关系
  2. 现在有个一个 序列: a [   ] = { 1 , 2 , 3 , . . , k , k − 1 , . . , k − ( n − d ) } a[~]=\{1,2,3,..,k,k-1,..,k-(n-d)\} a[ ]={1,2,3,..,k,k1,..,k(nd)},
  3. 让我们自己构造出一个 k 元全排列:p,
  4. 通过我们构造的这个全排列 p 我们可以求出来一个,序列 b [   ] = { p [ a [ 1 ] ] , p [ a [ 2 ] ] , . . . , p [ a [ n ] ] } b[~]=\{p[a[1]],p[a[2]],...,p[a[n]]\} b[ ]={p[a[1]],p[a[2]],...,p[a[n]]},
  5. 要求 b 中的逆序数的数量 <= a 中逆序数的数量,在 b 字典尽量大的前提下,
  6. 让我们输出这个的构造的 p,这里注意题目说符合题意的 p 是唯一的
  7. 注意:数组下标从均从 1 开始

思路

  1. 这题我是找规律做出的来的,
  2. 首先我们观察序列: a [   ] = { 1 , 2 , 3 , . . , k , k − 1 , . . , k − ( n − d ) } a[~]=\{1,2,3,..,k,k-1,..,k-(n-d)\} a[ ]={1,2,3,..,k,k1,..,k(nd)},后半部分存在对称的部分为: k , . . . , k + 1 , k + 2 , k , k − 1 , k − 2 , . . , k − ( n − d ) {k,...,k+1,k+2,k,k-1,k-2,..,k-(n-d)} k,...,k+1,k+2,k,k1,k2,..,k(nd), 关于 k 对称,两边元素的值向外逐渐递减,
  3. 那么因为:a 存在对称,那么无论 p 是什么样的排列,根据的序列 b 的定义, b [   ] = { p [ a [ 1 ] ] , p [ a [ 2 ] ] , . . . , p [ a [ n ] ] } b[~]=\{p[a[1]],p[a[2]],...,p[a[n]]\} b[ ]={p[a[1]],p[a[2]],...,p[a[n]]}, 那么 b 必定也是存在部分对称的情况,
  4. 那么的
    1. b 的对称部分为:    p [ 2 ∗ k − n ] , . . .    p [ k − 2 ] ,    p [ k − 1 ] ,    p [ k ] ,    p [ k − 1 ] ,    p [ k − 2 ] , . . ,    p [ 2 ∗ k − n ] {~~p[2*k-n],...~~p[k-2],~~p[k-1],~~p[k],~~p[k-1],~~p[k-2],..,~~p[2*k-n]}   p[2kn],...  p[k2],  p[k1],  p[k],  p[k1],  p[k2],..,  p[2kn]
    2. 那么 b 不对称部分为: p [ a [ 1 ] ] ,    p [ a [ 2 ] ] , . . . , p [ a [ 2 ∗ k − n − 1 ] ] p[a[1]],~~p[a[2]],...,p[a[2*k-n-1]] p[a[1]],  p[a[2]],...,p[a[2kn1]]
  5. 找规律发现:如果我得出的 b,要想最优的话,
    1. 那么 b 的不对称部分保持不变,仍然为: p [ a [ 1 ] ] ,    p [ a [ 2 ] ] , . . . , p [ a [ 2 ∗ k − n − 1 ] ] p[a[1]],~~p[a[2]],...,p[a[2*k-n-1]] p[a[1]],  p[a[2]],...,p[a[2kn1]]
    2. 对称部分变为: p [ k ] , p [ k − 1 ] , . . . , p [ 2 ∗ k − n ] , . . . , p [ k − 1 ] , p [ k ] p[k],p[k-1],...,p[2*k-n],...,p[k-1],p[k] p[k]p[k1]...p[2kn]...p[k1]p[k],
  6. 我们通过最优的 b 的构造出,从而反推出的 p,具体 p 的构造直接看代码把,,
  7. 有想证明的大佬自行证明一下吧,

代码


#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <string>
#include <string>
#include <map>
#include <bitset>
#include <vector>
void fre() { system("clear"), freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { system("clear"), freopen("A.txt", "r", stdin);}
void Run(int x = 0) {     
#ifdef ACM  //宏定义免注释 freopen
    if(! x) fre(); else Fre();
#endif
}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define db double
#define ll long long
#define ull unsigned long long
#define Pir pair<ll, ll>
#define m_p make_pair
#define for_(i, s, e) for(ll i = (ll)(s); i <= (ll)(e); i ++)
#define rep_(i, e, s) for(ll i = (ll)(e); i >= (ll)(s); i --)
#define memset(a, b, c) memset(a, (int)b, c);
#define size() size() * 1LL
#define sc scanf
#define pr printf
#define sd(a) scanf("%lld", &a)
#define ss(a) scanf("%s", a)
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define esp 1e-7
#define mod (ll)(1e9 + 7)
using namespace std;
/*=========================ACMer===========================*/
const ll mxn = 2e5 + 10;
ll ar[mxn];
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }
ll lcm(ll a, ll b) { return a * b / gcd(a, b); }


int main()
{
    Run();
    ll T; sd(T);
    while(T --)
    {
        ll n, k;
        sc("%lld %lld", &n, &k);
        ll d = n - k + 1;
        for_(i, 1, k - d)  pr("%lld ", i);
        rep_(i, k, k - d + 1) pr("%lld ", i);
        pr("\n");
    }

    return 0;
}




D. Program(维护)

题意

  1. 给我们一个长度为 n 仅由 +、- 字符组成的字符串 s,有一个变量 x 的初始值为 0,

    1. '+' 代表:令 x+=1,
    2. '-' 代表:令 x-=1
  2. 又给我们了 m 次操作,每次操作给一个区间 [l, r], 意思是如果把这个 s 中位于 [l,r] 区间内的字符舍弃,其他字符的相对位置不变的话形成 s’,求出从 s’ 第一个字符,到最后一个字符一次执行相应位置的字符所代表的操作,问会有多少个不同的 x 产生,在执行操作期间,

思路

  1. 我们先不考虑从 s 中删除的一个子串,考虑执行 s 这个命令字符串,会产生多少个不同的 x,看下面执行 s 时候 x 的值的变化图,可以得出的 x 的不同的值数量为区间的最大值与最小值之差在加上 + 1。
    在这里插入图片描述
  2. 先我们有了删除 s 中的某个子串,形成 s’(如上图绿色部分的操作),让后让求 s’所能产生的不同 x 的数量,那么我们可以维护前缀的最大最小值,和后缀的最大最小值,
    1. 前缀的最大最小值直接维护就可以得到,
 for_(i, 1, n)                       //维护前缀最大、最小值
        {
            if(s[i] == '+') now += 1;
            if(s[i] == '-') now -= 1;
            mx = max(mx, now);
            mn = min(mn, now);
            seg1[i] = (Node){ mx, mn, now };
        }
  1. 后缀的最大、最小值,
mx = mn = now = 0;
        rep_(i, n, 1)                       //从后往前维护以 i 为起点的最大、最小值
        {
            if(s[i] == '+') now += 1;
            if(s[i] == '-') now -= 1;
            mx = max(mx, now);
            mn = min(mn, now);
            seg2[i] = (Node){ now - mn, now - mx, 0 };
        }
		//这里解释一下为什么?以 i 为起点的最大值是 now - mn,
		//首先我们要确定 now 对于 i 这个位置是一个定值,
		//而 mn 是 j 位置(j>=i)的一个son最小值,从 j 位置的 son 转移到 i 位置的 son 必定是拥有相对'+' 号操作最多的哪段,(感性理解一下就是 从一个 数字 a 变成一个数字 b,那么 a 越小那么,a 变成 b 就需要的+1 操作越多,那么就是'+'操作越多!!!)

代码

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <algorithm>
#include <string>
#include <string>
#include <map>
#include <bitset>
#include <vector>
void fre() { system("clear"), freopen("A.txt", "r", stdin); freopen("Ans.txt","w",stdout); }
void Fre() { system("clear"), freopen("A.txt", "r", stdin);}
void Run(int x = 0) {     
#ifdef ACM  //宏定义免注释 freopen
    if(! x) fre(); else Fre();
#endif
}
#define ios ios::sync_with_stdio(false)
#define Pi acos(-1)
#define pb push_back
#define fi first
#define se second
#define db double
#define ll long long
#define ull unsigned long long
#define Pir pair<ll, ll>
#define m_p make_pair
#define for_(i, s, e) for(ll i = (ll)(s); i <= (ll)(e); i ++)
#define rep_(i, e, s) for(ll i = (ll)(e); i >= (ll)(s); i --)
#define memset(a, b, c) memset(a, (int)b, c);
#define size() size() * 1LL
#define sc scanf
#define pr printf
#define sd(a) scanf("%lld", &a)
#define ss(a) scanf("%s", a)
#define inf 0x3f3f3f3f
#define INF 0x3f3f3f3f3f3f3f3f
#define esp 1e-7
#define mod (ll)(1e9 + 7)
using namespace std;
/*=========================ACMer===========================*/
const ll mxn = 2e5 + 10;

struct Node
{
    ll mx, mn, now;
} seg1[mxn], seg2[mxn];
char s[mxn];




int main()
{
    Run();
    ll T; sd(T);
    while(T --)
    {
        ll n, m;
        sc("%lld %lld", &n, &m);
        ss(s + 1);
        ll mx = 0, mn = 0, now = 0;
        for_(i, 1, n)                       //维护前缀最大、最小值
        {
            if(s[i] == '+') now += 1;
            if(s[i] == '-') now -= 1;
            mx = max(mx, now);
            mn = min(mn, now);
            seg1[i] = (Node){ mx, mn, now };
        }

        mx = mn = now = 0;
        rep_(i, n, 1)                       //从后往前维护以 i 为起点的最大、最小值
        {
            if(s[i] == '+') now += 1;
            if(s[i] == '-') now -= 1;
            mx = max(mx, now);
            mn = min(mn, now);
            seg2[i] = (Node){ now - mn, now - mx, 0 };
        }

        seg1[0] = seg2[n + 1] = (Node){ 0, 0, 0 };        //特殊处理一下边界,防止越界问题
        ll l, r;
        while(m --)
        {
            sc("%lld %lld", &l, &r);
            ll maxx = max(seg1[l - 1].mx, seg1[l - 1].now + seg2[r + 1].mx); 
            ll minn = min(seg1[l - 1].mn, seg1[l - 1].now + seg2[r + 1].mn);
            ll ans = maxx - minn + 1;

            pr("%lld\n", ans);
        }
    }

    return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
"educational codeforces round 103 (rated for div. 2)"是一个Codeforces平台上的教育性比赛,专为2级选手设计评级。以下是有关该比赛的回答。 "educational codeforces round 103 (rated for div. 2)"是一场Codeforces平台上的教育性比赛。Codeforces是一个为程序员提供竞赛和评级的在线平台。这场比赛是专为2级选手设计的,这意味着它适合那些在算法和数据结构方面已经积累了一定经验的选手参与。 与其他Codeforces比赛一样,这场比赛将由多个问题组成,选手需要根据给定的问题描述和测试用例,编写程序来解决这些问题。比赛的时限通常有两到三个小时,选手需要在规定的时间内提交他们的解答。他们的程序将在Codeforces的在线评测系统上运行,并根据程序的正确性和效率进行评分。 该比赛被称为"educational",意味着比赛的目的是教育性的,而不是针对专业的竞争性。这种教育性比赛为选手提供了一个学习和提高他们编程技能的机会。即使选手没有在比赛中获得很高的排名,他们也可以从其他选手的解决方案中学习,并通过参与讨论获得更多的知识。 参加"educational codeforces round 103 (rated for div. 2)"对于2级选手来说是很有意义的。他们可以通过解决难度适中的问题来测试和巩固他们的算法和编程技巧。另外,这种比赛对于提高解决问题能力,锻炼思维和提高团队合作能力也是非常有帮助的。 总的来说,"educational codeforces round 103 (rated for div. 2)"是一场为2级选手设计的教育性比赛,旨在提高他们的编程技能和算法能力。参与这样的比赛可以为选手提供学习和进步的机会,同时也促进了编程社区的交流与合作。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值