Educational Codeforces Round 152 (Rated for Div. 2)

B. Monsters

题意:你的攻击力为k,你优先攻击血量最多的怪物,血量相同击杀编号小的,问怪物被击杀的顺序,

思路:我们可以知道最后肯定存在一个状态,所有怪物就差一次攻击就死了,这个状态取决于其血量是否可以整除k,那么我们计算这种状态,排序一下就行

#include 
using namespace std;
#define pi acos(-1)
#define xx first
#define yy second
#define endl "\n"
#define int long long
#define pb push_back
typedef pair PII;
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define Ysanqian ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
const int N = 1e6 + 10, M = 1010, inf = 0x3f3f3f3f, mod = 998244353;
int n, k;
struct node
{
    int x, id;
} a[N];
bool cmp(node a, node b)
{
    if (a.x == b.x)
        return a.id < b.id;
    return a.x > b.x;
}
int ans[N];
void solve()
{
    int n, k;
    cin >> n >> k;
    for (int i = 1; i <= n; i++)
    {
        int xx;
        cin >> xx;
        if (xx % k != 0)
            a[i].x = xx % k;
        else
            a[i].x = k;
        a[i].id = i;
    }
    sort(a + 1, a + 1 + n, cmp);

    for (int i = 1; i <= n; i++)
    {
        cout << a[i].id << " ";
    }
    cout << endl;
}
signed main()
{
    Ysanqian;
    int T;
    // T = 1;
    cin >> T;
    while (T--)
        solve();
    return 0;
}

C. Binary String Copying

题意:给你一个01串,m个操作,每次给出左端点,右端点,将其左右端点之间的字符串排序

思路:对区间[ l , r ],如果区间已经有序等于没操作.

对于一个区间,显然前缀的0和后缀的1是没用的,所以我们只需找到第一个1的位置 ′,最后一个0的位置′,其实等价于给[′ , ′]排序,拿个set维护以下这种等价类有多少种即可

思路转之知乎大佬

#include 
using namespace std;
#define pi acos(-1)
#define X first
#define Y second
#define endl "\n"
#define int long long
#define pb push_back
typedef pair PII;
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define Ysanqian ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
const int N = 1e6 + 10, M = 1 << 10, inf = 0x3f3f3f3f, mod = 998244353;
int n, m;
void solve()
{
	string s;
	set res;
	cin >> n >> m;
	cin >> s;
	vector pre(n, -1), back(n, n); // 初始化就是把1111......000000这种情况解决了,这样就是无前缀0,无后缀1,相当于(-1~n)
	for (int i = 0; i < n; i++)			// 前缀0
	{
		if (i != 0)
			pre[i] = pre[i - 1];
		if (s[i] == '0')
			pre[i] = i;
	}
	for (int i = n - 1; i >= 0; i--) // 后缀1,逆序前缀就行
	{
		if (i != n - 1)
			back[i] = back[i + 1];
		if (s[i] == '1')
			back[i] = i;
	}
	for (int i = 1; i <= m; i++)
	{
		int l, r;
		cin >> l >> r;
		l--, r--;
		int rr = pre[r], ll = back[l];
		if (ll > rr)
			res.insert({-1, -1});
		else
			res.insert({ll, rr});
	}
	cout << res.size() << endl;
}
signed main()
{
	Ysanqian;
	int T;
	// T=1;
	cin >> T;
	while (T--)
		solve();
}

D. Array Painting

题意:就是跟你一个0,1,2的全是蓝色的序列,让你通过两个操作使其全变为红色且花费最小,

1:花费一元,让一个数变为红色

2:让一个非0的红色元素值减1,选择它相邻的一个元素使其变红

思路:接贪心即可, 有 2 的话先操作 2 , 2 可以花费一元,向两侧扩展,可以使一个非零区间加上这个区间的两端的0,变为红色, 1 的话只能向 1 侧扩展,我们默认左传,它可以花费一让一个全一序列加上其左端的0为红,如果左端的没有0,我能让右端点的0变红,具体见代码注释

#include 
using namespace std;
#define pi acos(-1)
#define xx first
#define yy second
#define endl "\n"
#define int long long
#define ull unsigned long long
#define pb push_back
typedef pair PII;
#define max(a, b) (((a) > (b)) ? (a) : (b))
#define min(a, b) (((a) < (b)) ? (a) : (b))
#define Ysanqian ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
const int N = 1e6 + 10, M = 1010, inf = 1e11, mod = 998244353, P = 13331;
bool st[N];
int n;
void solve()
{
    int ans = 0;
    cin >> n;
    vector a(n);
    for (int i = 0; i < n; i++)
        cin >> a[i];
    for (int i = 0; i < n; i++)
    {
        if (a[i] == 0) // 如果是零我们直接跳过
            continue;
        int j = i, flag = 0;
        while (j < n && a[j] != 0) // 如果不是是零我们就继续向后走直到再遇见0
        {
            if (a[j] == 2) // 如果再次过程中遇到2,标记一下,应为2可以花费一就可以使这一段全不为0的区间并且加上两端的两个0变为红色
                flag = 1;
            j++;
        }
        if (flag) // 标记两端的0变成红色了
        {
            st[i - 1] = st[j] = 1;
        }
        else // 如果没有2
        {
            if ((i - 1) >= 0 && !st[i - 1]) // 左端为0我们就让1的红色左穿即可
                st[i - 1] = 1;
            else // 反之右传
                st[j] = 1;
        }
        ans++;     // 我们一定用了一钱让2或1变红,因为只有非0点才可以到这
        i = j - 1; // 跟新坐标点即可,我们最好将其跟新为j-1,或j,因为如果我们跟新更新成j+1的化,j这个0,就不能作为下一个2的左端点了
    }
    for (int i = 0; i < n; i++) // 看一下还有那些0点没有变红
        if (a[i] == 0 && !st[i])
            ans++;
    cout << ans << endl;
}
signed main()
{
    Ysanqian;
    int T;
    T = 1;
    // cin >> T;
    while (T--)
        solve();
    return 0;
}

你可能感兴趣的:(codeforces,c++,算法,思维)