Codeforces Round #753 (Div. 3) (A - G)

A. Linear Keyboard

暴力水题 用map来标记一下就行

代码

#include <bits/stdc++.h>

using namespace std;

const int N = 28;

map<char, int> mp;

void solve()
{
	string str; cin >> str;
	mp.clear();
	for (int i = 0; i < 26; i ++ )
		mp[str[i]] = i + 1;
	int ans = 0;
	string s; cin >> s;
	for (int i = 1; i < s.size(); i ++ ) ans += abs(mp[s[i]] - mp[s[i - 1]]);
	cout << ans << endl;
}

int main()
{
	int t;
	scanf("%d", &t);

	while (t -- )
	{
		solve();
	}

	return 0;
}

B - Odd Grasshopper

找规律 每走四次就会返回起点 mod一下4走四步以内就可以找到答案

代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

void solve()
{
	ll x0, n;
	scanf("%lld%lld", &x0, &n);
	ll step = n % 4;
	n -= step;
	while (step)
	{
		n ++ ;
		if (x0 & 1) x0 += n;
		else x0 -= n;
		step -- ;
	}
	cout << x0 << endl;
}

int main()
{
	int t;
	scanf("%d", &t);

	while (t -- )
	{
		solve();
	}

	return 0;
}

C - Minimum Extraction

第 i 轮减去最小数 等于 本来的数减去本来数组中第 i 小的数
拍一下序 求最大值即可
代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 2e5 + 10;

int n;
ll a[N];

void solve()
{
	cin >> n;
	for (int i = 1; i <= n; i ++ ) scanf("%lld", &a[i]);
	sort(a + 1, a + 1 + n);
	ll nmin;
	for (int i = 1; i <= n; i ++ )
	{
		if (i == 1) nmin = a[i];
		else nmin = max(nmin, a[i] - a[i - 1]);
	}
	cout << nmin << endl;
}

int main()
{
	int t;
	scanf("%d", &t);

	while (t -- )
	{
		solve();
	}

	return 0;
}

D. Blue-Red Permutation

把所有蓝色块子都移动到左边 红色块子都移动到右边 看看两边会出现重复吗 如果不出现就是yes 出现就no

代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 2e5 + 10;

int n;
int b[N], r[N], a[N];
bool st[N];
char s[N];

void solve()
{
	int bcnt = 0, rcnt = 0;
	scanf("%d", &n);
	for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
	scanf("%s", s + 1);
	for (int i = 1; i <= n; i ++ )
		if (s[i] == 'B') b[ ++ bcnt] = a[i];
		else r[ ++ rcnt] = a[i];
	sort(b + 1, b + bcnt + 1); sort(r + 1, r + rcnt + 1);
	int tmp = 0;
	for (int i = 1; i <= bcnt; i ++ ) 
	{
		if (b[i] >= i) tmp ++ ;
		if (tmp != i) {puts("NO"); return;}
	}
	tmp = 0;
	for (int i = rcnt; i >= 1; i -- )
	{
		if (r[i] <= i + bcnt) tmp ++ ;
		if (tmp != (rcnt - i + 1)) {puts("NO"); return;}
	}
	puts("YES");
}

int main()
{
	int t;
	scanf("%d", &t);

	while (t -- )
	{
		solve();
	}

	return 0;
}

E. Robot on the Board 1

维护一下x轴位置最小值和位置最大值 以及y轴位置最小值和位置最大值 当任意一个轴中出现区间大于n(m)时就break 当前两轴的xmin和ymin就是最佳位置的偏移量

代码

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 2e5 + 10;

int n, m;
string s;

void solve()
{
	scanf("%d%d", &n, &m); cin >> s;
	int umin = 1, umax = 1, lmin = 1, lmax = 1;
	int nowx = 1, nowy = 1;
	for (int i = 0; i < s.size(); i ++ )
	{
		if (s[i] == 'L')
		{
			int tmp = nowx - 1;
			if (tmp < lmin)
			{
				if (lmax - tmp + 1 > m) break;
				lmin = tmp;
			}
			nowx = tmp;
		}
		else if (s[i] == 'R')
		{
			int tmp = nowx + 1;
			if (tmp > lmax)
			{
				if (nowx - tmp + 1 > m) break;
				lmax = tmp;
			}
			nowx = tmp;
		}
		else if (s[i] == 'U')
		{
			int tmp = nowy - 1;
			if (tmp < umin)
			{	
				if (umax - tmp + 1 > n) break;
				umin = tmp;
			}
			nowy = tmp;
		}
		else if (s[i] == 'D')
		{
			int tmp = nowy + 1;
			if (tmp > umax)
			{
				if (tmp - umin + 1 > n) break;
				umax = tmp;
			}
			nowy = tmp;
		}
	}

	cout << 2 - umin << ' ' << 2 - lmin << endl;
}

int main()
{
	int t;
	scanf("%d", &t);

	while (t -- )
	{
		solve();
	}

	return 0;
}

F - Robot on the Board 2

对于每个块 我们都可以进行一次dfs 但是很明显这样可能会超时所以要剪枝 我们可以用len[i][j]来表示从(i, j)走最多走多少步 只遍历那些入度为0的点 最后再找一下是否有单环 因为单环所有点入度都不为0 用stack的话会爆空间

代码

#include <bits/stdc++.h>

#define rep(i, n) for (int i = 1; i <= (n); i ++ )

using namespace std;

const int N = 2010;

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

int n, m;
char c[N][N], s[N];
int len[N][N];

int ans, col, row;

void maintain(int len, int i, int j)
{
    if (len > ans)
    {
        ans = len, row = i, col = j;
    }
}

void getpos(int &x, int &y)
{
    if (c[x][y] == 'L') y -- ;
    else if (c[x][y] == 'R') y ++ ;
    else if (c[x][y] == 'U') x -- ;
    else if (c[x][y] == 'D') x ++ ;
}

bool valid(int x, int y)
{
    if (x < 1 || x > n || y < 1 || y > m) return false;
    return true;
}

void solve()
{
    n = read(), m = read();
    rep(i, n){
        gets(s);
        rep(j, m){
            c[i][j] = s[j - 1];
            len[i][j] = 0;
        }
    }

    ans = 0;
    rep(i, n)
        rep(j, m){
            if (len[i][j]) continue;
            if (i != 1 && c[i - 1][j] == 'D') continue;
            if (i != n && c[i + 1][j] == 'U') continue;
            if (j != 1 && c[i][j - 1] == 'R') continue;
            if (j != m && c[i][j + 1] == 'L') continue;

            int x = i, y = j, nx, ny, cur = 0;
            while (true)
            {
                ++ cur, len[x][y] = -cur;
                nx = x, ny = y;
                getpos(nx, ny);
                if (!valid(nx, ny) || len[nx][ny]) break;
                x = nx, y = ny;
            }

            if (valid(nx, ny) && len[nx][ny] > 0) 
                cur += len[nx][ny];

            maintain(cur, i, j);

            x = i, y = j, ++ cur;
            while (x != nx || y != ny)
            {
                len[x][y] += cur;
                getpos(x, y);
            }

            if (!valid(nx, ny) || len[nx][ny] > 0) continue;

            cur += len[nx][ny];
            do{
                len[x][y] = cur;
                getpos(x, y);
            } while(x != nx || y != ny); 
        }

    rep(i, n)
        rep(j, m){
            if (len[i][j]) continue;
            int cur = 0, x = i, y = j;
            while (valid(x, y) && !len[x][y])
            {
                ++ cur; len[x][y] = -1;
                getpos(x, y);
            }
            maintain(cur, i, j);
        }

    printf("%d %d %d\n", row, col, ans);
}

int main()
{
    int t;
    t = read();

    while (t -- )
    {
        solve();
    }

    return 0;
}

G - Banquet Preparations 1

题意 : 给定两个数组 a 和 b 对于第 i 组 a和b总共要剪去m 问1-n 操作之后 ∣ ∑ a i − ∑ b i ∣ |\sum a_i - \sum b_i | aibi的最小值为多少
∑ a i \sum a_i ai ∑ b i \sum b_i bi 都是变值 很难求 我们可以将其中一个变成定值
即我们用 tot 表示 ∑ ( a i + b i − m ) \sum (a_i+b_i-m) (ai+bim) 然后用 minsum 来表示所有b减去可能值后最小的值 maxsum表示所有b减去可能值之后的最大的值 则可以得到 tot - bsum * 2 = asum - bsum 即 ∣ ∑ a i − ∑ b i ∣ |\sum a_i - \sum b_i| aibi 则有这样几种情况
tot < minsum * 2 则b要尽量取小才能使值变小
tot > maxsum * 2 则b要尽量取大才能使值变大
minsum * 2 < tot < maxsum * 2 如果tot为奇 则结果为1 否则为 0

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 2e5 + 10;

int n, m;
ll a[N], b[N];

void solve()
{
    scanf("%d%d", &n, &m);

    ll tot = 0, minsum = 0, maxsum = 0;
    for (int i = 1; i <= n; i ++ ) 
    {
        scanf("%lld%lld", &a[i], &b[i]);
        tot += (a[i] + b[i] - m);
        minsum += b[i] >= m ? b[i] - m : 0;
        maxsum += a[i] >= m ? b[i] : b[i] - (m - a[i]);
    }
    minsum *= 2, maxsum *= 2;

    if (tot <= minsum)
    {
        printf("%lld\n", minsum - tot);
        for (int i = 1; i <= n; i ++ )
            if (b[i] >= m) { a[i] = 0; b[i] = m; }
            else a[i] = m - b[i];
    }   
    else if (tot >= maxsum)
    {
        printf("%lld\n", tot - maxsum);
        for (int i = 1; i <= n; i ++ )
            if (a[i] >= m) { a[i] = m; b[i] = 0; }
            else b[i] = m - a[i];
    }
    else
    {
        if (tot & 1) puts("1");
        else puts("0");
        tot = (tot - minsum) / 2;
        for (int i = 1; i <= n; i ++ )
        {
            ll maxsub = b[i] >= m ? m : b[i];
            ll minsub = a[i] >= m ? 0 : m - a[i];

            if (maxsub - tot >= minsub)
            {
                b[i] = maxsub - tot; a[i] = m - b[i];
                tot = 0;
            }
            else 
            {
                b[i] = minsub; a[i] = m - b[i];
                tot -= maxsub - minsub;
            }
        }
    }

    for (int i = 1; i <= n; i ++ ) printf("%lld %lld\n", a[i], b[i]);
}

int main()
{
    int t;
    scanf("%d", &t);

    while (t -- )
    {
        solve();
    }

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值