训练(个人记录)

目录

2023年6月5号

Codeforces Round 877 (Div. 2) (补做)

B. Minimize Permutation Subarrays

2023年7月29日

Codeforces Round 886 (Div. 4)

E. Cardboard for Pictures

 Educational Codeforces Round 152 (Rated for Div. 2)

 C. Binary String Copying

Codeforces Round 893 (Div. 2)Codeforces Round 893 (Div. 2)Codeforces Round 893 (Div. 2)

B. The Walkway 

C. Yet Another Permutation Problem


算法小白,记录一些觉得需要记录一下的题目。

2023年6月5号

Codeforces Round 877 (Div. 2) (补做)

B. Minimize Permutation Subarrays

写的时候想的不够全面,一直在考虑1周围两个值应该替换哪个,但是只要在1和2之间插入最大值,就可以打断除数列本身的其他所有子数列组合。写的时候没有草稿纸,纯靠脑子想样例,在纸上手写几种情况应该能快点找到点。还是太菜了。

#include<iostream>
#include<algorithm>

using namespace std;

const int N = 2e5 + 10;

int main()
{
	int t;
	cin >> t;
	while (t--)
	{
		int n;
		int index,lindex,rindex;
		int num[N] = {0};
		cin >> n;
		for (int i = 1; i <= n; i++)
		{
			cin >> num[i];
			if (num[i] == n) index = i;
			if (num[i] == 1) lindex = i;
			if (num[i] == 2) rindex = i;
		}
		if (lindex > rindex) swap(lindex, rindex);
		if (index > lindex && index < rindex) cout << 1 << " " << 1 << endl;
		else if (index < lindex) cout << index << " " << lindex << endl;
		else if (index > rindex) cout << index << " " << rindex << endl;
	}
	return 0;
}

2023年7月29日

Codeforces Round 886 (Div. 4)

E. Cardboard for Pictures

题目大意:有n个正方形,给出总面积和内部正方形的边长,求w的长度

思路:原本想通过面积公式看看能不能算出来,但是最后是一个一元二次方程

看了题解,可以用二分来找到适合的w。

#include<bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 2e5 + 10;

ll a[N];

void solve()
{
	ll n, s;
	cin >> n >> s;
	for (int i = 1; i <= n; i++) cin >> a[i];

	int l = 0, r = 1e9, middle;
	while (l + 1 != r)
	{
		middle = (l + r) >> 1;
		ll sum = 0;
		for (int i = 1; i <= n; i++)
		{
			sum += (a[i] + middle) * (a[i] + middle);
			if (sum > s)break;
		}

		if (sum > s) r = middle;
		else if (sum < s) l = middle;
		else { cout << middle/2 << endl; return; }
	}
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	int _;
	cin >> _;
	while (_--)
		solve();

	return 0;
}

 Educational Codeforces Round 152 (Rated for Div. 2)

 C. Binary String Copying

大意:有一串01字符串,对其进行复制,每一次对复制串给定的区间 [l,r] 进行排序,不会影响原字符串,求不同的字符串数,且原字符串不计入,如果复制串=原串则可计入

题解:对于一个区间来说,区间最左侧的0和最右侧的1不会影响排序结果
那么对于输入的L和R,得到距离 L 最近的1所在下标 L'和距离R最近的0所在下标R',
只要L和R得到的L'和R'范围一样,则排序的结果也是一样的
所以只要用set存储{L',R'}即可,如果L’>R'则说明输入的区间已经是有序,不会改变,存入{-1,-1}

#include<bits/stdc++.h>

using namespace std;

typedef pair<int,int>PII;
const int N = 2e5 + 10;

int a[N];

void solve()
{
	int n, m;
	string s;
	cin >> n >> m;
	cin >> s;

	vector<int>pre(n, -1), back(n, n);//pre储存0的位置,back储存1的位置

	for (int i = 0; i < n; i++)
	{
		if (i!=0) pre[i] = pre[i - 1];
		if (s[i] == '0') pre[i] = i;
	}

	for (int i = n - 1; i >= 0; i--)
	{
		if (i != n - 1) back[i] = back[i + 1];
		if (s[i] == '1') back[i] = i;
	}

	set<PII>res;

	for (int i = 0; i < m; i++)
	{
		int l, r;
		cin >> l >> r;
		l--; r--;

		int ll = back[l], rr = pre[r];

		if (ll > rr) res.insert({ -1,-1 });
		else res.insert({ ll,rr });
	}

	cout << res.size() << endl;
}

int main()
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);

	int _;
	cin >> _;
	while (_--)
	{
		solve();
	}
	return 0;
}

2023年8月17日

最近在刷牛客题库,没怎么补cf题 

Codeforces Round 893 (Div. 2)

B. The Walkway 

 

 

 

 题目大意:一条路上有1-n编号的椅子,同时有m个饼干商人,P每走一步耗时一分钟,当:

P在第一张椅子处会吃饼干

P所在的椅子处有饼干商人 P会吃饼干

P距离上一次吃饼干过去了d分钟

求:移除一个饼干商人能吃到最少饼干数已经能吃到最少饼干数的商人的数量

思路:样例二吃饼干的序列为 1 3 5 7  8

假设我们移除5处的商人,3前面的吃饼干状态不会被影响,7后面吃饼干的状态也不会被影响,因此只需计算(7-3-1)/d+3前面的吃饼干数+7后面的吃饼干数就可以得出移除5后的吃饼干数,算出每个饼干商人的贡献

可以用前缀和和后缀和存放正常吃饼干的数量

为了方便计算在第一个饼干商人的贡献前假设有个编号1的饼干商人,同理在最后一个饼干商人后面假设有个编号为n+1的商人存在

ac代码

#include<bits/stdc++.h>

using namespace std;

typedef pair<int, int>PII;
typedef long long ll;
const int N = 1e5 + 10;

int a[N],b[N],c[N];

void solve()
{
    int n, m, d;
    cin >> n >> m >> d;

    for (int i = 0; i <= m + 1; i++)a[i] = b[i] = c[i] = 0;

    a[0] = 1; a[m + 1] = n + 1;
    for (int i = 1; i <= m; i++) cin >> a[i];

    //后缀和
    for (int i = m; i >= 1; i--) b[i] = b[i + 1] + (a[i + 1] - a[i] - 1) / d + 1;

    //前缀和
    c[0] = 1;
    for (int i = 1; i <= m; i++)
    {
        c[i] = c[i - 1] + (a[i] - a[i - 1] - 1) / d + 1;
        if (a[i] == a[i - 1]) c[i] = 1;//第一个商人位于起点
    }
    int ans = 1, res = 0;
    int st = 1; int i = 1;

    int num = 0,mi=1e9;
    map<int, int>cou;
    for (int i = 1; i <= m; i++)
    {
        num = c[i - 1] + b[i + 1] + (a[i + 1] - a[i - 1] - 1) / d;
        cou[num]++;
        if (num < mi) mi = num;
    }
  
    cout << mi << " " << cou[mi] << endl;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int _ = 1;
    cin>>_;
    while (_--)
        solve();
}

C. Yet Another Permutation Problem

 

 大意:有一个序列成环,相邻两个数的gcd记为di,求最大的不同gcd的序列摆放位置

思路:贪心,不同的gcd数量最多为n/2个,

n/2,n的gcd为n/2,假如有gcd为n/2+1,那么另一个数最小也会为n+2,超出范围了,因此最好的情况就是n/2以内的gcd全部存在。

如果a是b的倍数,那么gcd就是b,

贪心地想尽量使1-n/2的所有数都出现,从1开始,乘最小的倍数2

假设n为10

1 2 4 8 (16)16大于10,继续选择还没有选择的

1 2 4 8 3 6 5 10 7 9

这样子构造出现的gcd为1 2 4 3 5,1-n/2都出现了

ac代码

#include<bits/stdc++.h>

using namespace std;

typedef pair<int, int>PII;
typedef long long ll;
const int N = 1e5 + 10;

int a[N], vis[N];

void solve()
{
    memset(vis, 0, sizeof(vis));
    int n;
    cin >> n;
    int j = 0;
    for (int i = 1; i <= n; i++)
    {
        int tmp = i;
        while (tmp <= n && !vis[tmp])
        {
            a[++j] = tmp;
            vis[tmp] = 1;
            tmp *= 2;
       }
    }

    for (int i = 1; i <= n; i++)cout << a[i] << " ";
        cout << endl;
}

int main()
{
    ios::sync_with_stdio(0);
    cin.tie(0);
    cout.tie(0);

    int _ = 1;
    cin>>_;
    while (_--)
        solve();
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值