Codeforces#744(Div3)ABCDE1E2F

Codeforces#744(Div3)

今天要补2场CF的题目,算做给队友的生日礼物。

比赛传送门

A. Casimir’s String Solitaire

SumA+SumC==SumB?“Yes”:“No”;

#include <bits/stdc++.h>

using namespace std;

int main() {
    int T;
    cin >> T;
    while (T--) {
        string s;
        cin >> s;
        int s1 = 0, s2 = 0;
        for (int i = 0; i < s.length(); i++) {
            if (s[i] == 'B') s1++;
            else s2++;
        }
        if (s1 == s2)
            cout << "YES" << endl;
        else cout << "No" << endl;
    }
}

B. Shifting Sort

洗牌题,意思是通过多次 l r d lrd lrd的洗牌,实现整个序列非递减。
l r d lrd lrd:意思是 [ l , r ] [l,r] [l,r]区间内长度为 d d d的部分向左循环变序。
模拟即可。

#include <bits/stdc++.h>

using namespace std;
int l[100], r[100], d[100];
int a[100], b[100];

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        int n;
        scanf("%d", &n);
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            b[i] = a[i];
        }
        int cnt = 0;
        sort(b + 1, b + 1 + n);
        int p = 0;
        for (int i = 1; i <= n; i++) {
            p = 0;
            for (int j = i; j <= n; j++) {
                if (a[j] == b[i]) {
                    for (int k = j; k > i; k--) {
                        a[k] = a[k - 1];
                    }
                    p = j;
                    break;
                }
            }
            if (p != i)
                l[++cnt] = i, r[cnt] = p, d[cnt] = p - i;
        }
        printf("%d\n", cnt);
        for (int i = 1; i <= cnt; i++)
            printf("%d %d %d\n", l[i], r[i], d[i]);
    }

}


C. Ticks

问你能不能把V连完,没有多出来的*。
我不太会写搜索,经常写裂,所以写了个循环,反正过了。

#include <bits/stdc++.h>

using namespace std;
string a[100];

int main() {
    int T;
    cin >> T;
    while (T--) {
        int n, m, k;
        cin >> n >> m >> k;
        for (int i = 0; i < n; i++)
            cin >> a[i];
        int d;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++) {
                d = 0;
                if (a[i][j] == '.') continue;
                while (a[i - d - 1][j + d + 1] != '.' && a[i - d - 1][j - d - 1] != '.'
                       && d < i && d < j && j + d + 1 < m)
                    d++;

                if (d >= k) {
                    for (int sn = 0; sn <= d; sn++) {
                        a[i - sn][j - sn] = 'Q';
                        a[i - sn][j + sn] = 'Q';
                    }
                }

            }
        int f = 0;
        for (int i = 0; i < n; i++)
            for (int j = 0; j < m; j++)
                if (a[i][j] == '*') {
                    f = 1;
                    break;
                }
        if (f) cout << "No\n";
        else cout << "Yes\n";
    }
}

D.Productive Meeting

优先队列每次选最大2个(-1),贪心放回去,直到剩余非零元素为0或者为1。

#include <bits/stdc++.h>

using namespace std;

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        priority_queue<pair<int, int>> q;
        vector<pair<int, int>> ans;
        int n;
        scanf("%d", &n);
        int t;
        for (int i = 0; i < n; i++) {
            scanf("%d", &t);
            if (t)
                q.push({t, i});
        }
        pair<int, int> a, b;
        while (!q.empty()&&q.size()!=1) {

            a = q.top();
            q.pop();
            b = q.top();
            q.pop();
            ans.push_back({a.second, b.second});
            a.first--;
            b.first--;
            if (a.first) q.push(a);
            if (b.first) q.push(b);
        }
        printf("%d\n", int(ans.size()));
        for (int i = 0; i < ans.size(); i++)
            printf("%d %d\n", ans[i].first+1, ans[i].second+1);

    }
}

E1. Permutation Minimization by Deque

贴代码吧,过了快一万人了。

#include <bits/stdc++.h>

using namespace std;

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        deque<int> q;
        int n;
        scanf("%d", &n);
        int t;
        for (int i = 1; i <= n; i++) {
            scanf("%d", &t);
            if (q.empty()) {
                q.push_front(t);
            } else if (t < q.front()) {
                q.push_front(t);
            } else {
                q.push_back(t);
            }
        }
        while (!q.empty()) {
            printf("%d ", q.front());
            q.pop_front();
        }
        printf("\n");
    }
}

E2. Array Optimization by Deque

贪心题,贪心策略就是把一个数字放前面还是放后面,使得序列最终逆序对最少,那就都放放看,对每个元素取最优即可。

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int maxn = 2e5 + 10;
int a[maxn], tr[maxn];
int n;

ll lowbit(int x) {
    return x & -x;
}

void add(int x, int y) {
    while (x <= n) {
        tr[x] += y;
        x += lowbit(x);
    }
}

ll getsum(int x) {
    ll sum = 0;
    while (x) {
        sum += tr[x];
        x -= lowbit(x);
    }
    return sum;
}

int main() {
    int T;
    scanf("%d", &T);
    while (T--) {
        scanf("%d", &n);
        memset(tr, 0ll, sizeof(tr));
        vector<ll> v;
        for (int i = 1; i <= n; i++) {
            scanf("%d", &a[i]);
            v.push_back(a[i]);
        }
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
        for (int i = 1; i <= n; i++) {
            a[i] = lower_bound(v.begin(), v.end(), a[i]) - v.begin() + 1;
        }
        ll ans = 0;
        for (int i = 1; i <= n; i++) {
            ll h = getsum(a[i] - 1), t = getsum(n) - getsum(a[i]);
            if (h <= t) ans += h;
            else ans += t;
            add(a[i], 1);
        }
        printf("%lld\n", ans);
    }
}
重温树状数组:

我们假设一个数组 a [ n ] = 0 a[n]=0 a[n]=0时表示数字 n n n在序列中没有出现过, a [ n ] = 1 a[n]=1 a[n]=1表示数字 n n n在序列中出现过。
a a a对应的树状数组为 t r [ n ] tr[n] tr[n],则 t r [ n ] tr[n] tr[n]对应维护的是数组 a [ n ] a[n] a[n]的内容,可用于求 a a a中某个区间的值的和。

树状数组的插入函数的含义:
void add(int x, int y) {
    while (x <= n) {
        tr[x] += y;
        x += lowbit(x);
    }
}

在求逆序数这个问题中,我们的add函数通常使用为 i n s e r t ( i , 1 ) insert( i , 1 ) insert(i,1),即将数组a[i]的值加1 (A数组开始应该初始化为0,所以也可以理解为设置a[ i ]的值为1,即将数字i 加入到序列的意思 )。
同时维护 t r tr tr数组的值。

树状数组中区间求和函数含义:

ll getsum(int x) {
    ll sum = 0;
    while (x) {
        sum += tr[x];
        x -= lowbit(x);
    }
    return sum;
}

该函数的作用是用于求序列中小于等于数字 i 的元素的个数。序列中比元素a大的数的个数,可以用 g e t s u m ( n ) − g e t s u m ( a ) getsum(n) - getsum(a) getsum(n)getsum(a)即可( i 表示此时序列中元素的个数)。

首先来看如何减小问题的规模:
要想求一个序列 a b c d a b c d abcd,的逆序数的个数,可以理解为先求出 a b c a b c abc的逆序数的个数 k 1 k1 k1,再在这个序列后面增加一个数 d d d,求d之前的那个序列中值小于d的元素的个数k2,则 k 1 + k 2 k1+k2 k1+k2即为序列 a b c d a b c d abcd的逆序数的个数。

所以本题进行一个 a n s ans ans的加。

F. Array Stabilization (AND version)

@bcj记得写题解!!

G. Minimal Coverage

队友的博客
我之后再补。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值