Codeforces Round #710 (Div. 3)

Codeforces Round #710 (Div. 3)

https://codeforces.com/contest/1506

昨天的vp

A. Strange Table

计算坐标,然后转化

#include <bits/stdc++.h>
#define  int long long

using namespace std;

void solve () {
    int n, m, z;
    cin >> n >> m >> z;
    // if (n * m == z) {
    //     cout << z << endl;
    //     return;
    // }
    int y = ceil(1.0*z/n), x = z%n;
    if (x == 0) x = n;
    //cout << x << ' ' << y << endl;
    cout << (x-1)*m+y << endl;
}

signed main () {
    int t;
    cin >> t;
    while (t --) {
        solve ();
    }
}

//坐标
//(ceil(x/m),x%m)

B. Partial Replacement

我是直接模拟填距离
似乎也可以dp,改天学习一下

#include <bits/stdc++.h>
#define  int long long

using namespace std;

void solve () {
    int n, k;
    string s;
    cin >> n >> k >> s;
    vector <int> v; //坐标

    for (int i = 0; i < n; i ++) {
        if (s[i] == '*')    v.push_back (i);
    }
    int m = v.size ();
    if (m <= 2) {
        cout << m << endl;
        return ;
    }
    // for (auto i : v)    cout << i << ' ';
    // cout << endl;

    int ans = 2;
    int len = 0;
    for (int i = 1; i < m; i ++) {
        len += v[i] - v[i-1];
        //cout << "len=" << len << endl;
        if (len == k && i != m-1)   ans ++, len = 0;
        else if (len > k)   i --, len = 0, ans ++;
        //len += v[i] - v[i-1];
    }

    cout << ans << endl;
}
//两个x之间的坐标差<=k

signed main () {
    int t;
    cin >> t;
    while (t --) {
        solve ();
    }
}

C. Double-ended Strings

找到最长相等连续子串,长度为len
答案为n+m-len*2
做法:拿小的在大的上面偏移,匹配最长长度
暴力,注意细节
因为细节疯狂WA

#include <bits/stdc++.h>

using namespace std;

void solve () {
    string a, b;
    cin >> a >> b;
    if (a == b) {
        cout << "0\n";
        return ;
    }
    int n = a.size (), m = b.size ();
    if (n < m)  swap (n, m), swap (a, b);
    //cout << n << ' ' << m << endl;
    
    int ans = 0;
    for (int i = 0; i < n; i ++) {
        int len = 0;
        for (int j = 0; j < m; j ++) {
            if (b[j] != a[i]) {
                ans = max (ans, len);
                len = 0;
                continue;
            } 
            //cout << "len=" << len << endl;
            len ++;
            while (i+len<n && j+len<m && b[j+len] == a[i+len])   len++;
            ans = max (ans, len);
            len = 0;
        }
    }
    //cout << ans << endl;
    cout << n + m - ans * 2 << endl;

}

int main () {
    int t;
    cin >> t;
    while (t --) {
        solve ();
    }
}
//删前或后
//字符串匹配

//找到最长相等连续子串,长度为len
//答案为n+m-len*2

//case4:
// dhjak jsnasjhfks afasd
// ad jsnasjhfks vdafdser
// jsnasjhfks

//复杂度n^2

//拿小的在大的上面偏移,匹配最长长度

D. Epic Transformation

每次可以删两个不一样的
最少剩下几个

具体处理:用堆
每次拿两个不同的出来--

要对数量敏感啊!!这种大小关系的就要想到STL

#include <bits/stdc++.h>

using namespace std;
typedef pair<int, int> pii; //数量,种类
const int N = 2e5 + 5;
int a[N];

void solve () {
    map<int, int> mp;
    int n;
    cin >> n;
    for (int i = 0; i < n; i ++)
        cin >> a[i], mp[a[i]] ++;

    sort (a, a + n);
    priority_queue <pii> q; //默认降序

    for (int i = 1; i < n; i ++) {
        if (a[i] != a[i-1]) 
            q.push ({mp[a[i-1]], a[i-1]});
    }
    q.push ({mp[a[n-1]], a[n-1]}); //别忘了最后一个也要放上

    while (!q.empty ()) {
        auto a = q.top();
        q.pop();
        if (q.empty ()) {
            q.push (a);
            break;
        }
        auto b = q.top();
        q.pop();
        a.first --, b.first --; //配对
        if (a.first)    q.push (a);
        if (b.first)    q.push (b);
    }

    if (q.empty ())     cout << "0\n";
    else    cout << q.top().first << endl;
}

int main () {
    int t;
    cin >> t;
    while (t --) {
        solve ();
    }
}
//每次可以删两个不一样的
//最少剩下几个

//具体处理:用堆
//每次拿两个不同的出来--

//说白了还是stl不熟练

E. Restoring the Permutation

set维护可放的数字 + 二分查找
(还是STL不熟

#include <bits/stdc++.h>
#define IOS ios::sync_with_stdio (0);cin.tie(0);

using namespace std;
const int N = 2e5  + 5;
int n;

// void test () {
//     for (int i = 1; i <= n; i ++)   cout << b1[i] << ' ';cout << endl;
//     for (int i = 1; i <= n; i ++)   cout << vis1[i] << ' ';cout << endl;
// }

void solve () {
    cin >> n;
    set<int> s1, s2;
    deque <int> a(n+1), b1(n+1), b2(n+1);
    
    for (int i = 1; i <= n; i ++) {
        cin >> a[i], s1.insert (i), s2.insert (i); //默认递增
    
    }   
    
    for (int i = 1; i <= n; i ++) {
        if (a[i] != a[i-1]) {
            b1[i] = b2[i] = a[i];
            s1.erase (a[i]), s2.erase (a[i]);
        }     
        else {
            //min
            b1[i] = *(s1.begin());
            s1.erase (b1[i]);
            //max
            auto it = s2.lower_bound (a[i]); //大于等于
            it --; //第一个大于等于他的上一个(就是最大小于他的)
            b2[i] = *it;
            s2.erase (b2[i]);
        }
    }
    b1.pop_front(), b2.pop_front (); //首项是0

    for (auto i : b1)   cout << i << ' ';   cout << endl;
    for (auto i : b2)   cout << i << ' ';   cout << endl;
}

int main () {
    int t;
    cin >> t;
    while (t --)    solve ();
}

//每一段的首项固定
//暴力TLE

//优化:用集合来维护
//min: s.begin()为答案
//max: lower_bound()找到小于a[i]的最大元素

F. Triangular Paths

有一个 n 行的下三角矩阵
当 (i+j) % 2 == 0 时 (i, j) 有一条通往 (i + 1, j) 的边,否则 (i, j) 有一条通往 (i + 1, j + 1) 的边
可以花费 1 的代价令某一个点的出边在抵达 (i + 1, j)和 (i + 1, j + 1)之间互换

找规律:

(x-y)%2 为奇时,往右下走cost不变;否则cost++
迭代更新

#include <bits/stdc++.h>

using namespace std;
typedef pair<int, int> pii;
const int N = 200010;
int n;
pii e[N];

void solve () {
    cin >> n;
    for(int i = 1; i <= n; i ++)  cin >> e[i].first;
    for(int i = 1; i <= n; i ++)  cin >> e[i].second;
    e[0] = {1, 1};
    sort(e + 1, e + n + 1);

    int res = 0;
    for(int i = 1; i <= n; i ++) {
        int dx = e[i].first - e[i - 1].first, dy = e[i].second - e[i - 1].second;
        int t = dx - dy;
        if (t == 0) {
            if((e[i].first - e[i].second) % 2 == 0)  res += dx;  
        }
        
        else {
            if((e[i - 1].first - e[i - 1].second) % 2)  res += (t + 1) / 2; //上取整
            else  res += t / 2;
        }
    }
    cout << res << endl;
}

int main() {
    int t;  cin >> t;
    while (t --)    solve ();
}

G. Maximize the Remaining String

去重的基础上+单调栈
pos[]:记录每一个字母在序列中出现的最后位置
(括号太多。。。绕晕了。。检查了半天。。。麻)

#include <bits/stdc++.h>

using namespace std;
typedef pair<char, int> pci; //字符,下标
const int N = 2e5 + 5;
bool vis[28];
int pos[28];

void solve () {
    memset (vis, false, sizeof vis);
    memset (pos, 0, sizeof pos);
    string s;
    cin >> s;
    int n = s.size ();

    for (int i = 0; i < n; i ++)    pos[s[i] - 'a'] = i;
    //构造单调栈
    stack<int> stk;
    for (int i = 0; i < n; i ++) {
        if (vis[s[i] - 'a'])    continue;
        while (!stk.empty () && s[i] > s[stk.top ()] && i < pos[s[stk.top ()] - 'a'])
            vis[s[stk.top()] - 'a'] = false, stk.pop(); //不能能塞进去的踢出去
        stk.push (i), vis[s[i] - 'a'] = true;
    }
    //反向输出
    vector <char> v;
    while (!stk.empty ()) v.push_back (s[stk.top()]), stk.pop ();
    reverse (v.begin (), v.end ());
    for (auto i : v)    cout << i;  cout << endl;
}

int main () {
    int t;
    cin >> t;
    while (t --)    solve ();
}

//删掉相同的字符
//相同的一前s[i]一后s[j],比较s[i]与s[i+1],s[j]与s[j+1]
//如果s[i]<s[i+1],删s[i]
//如果s[i]>s[i+1],删s[j]
//如果s[i]==s[i+1](即j==i+1),删谁都行

//策略没问题,关键是不会操作

//没过去的点:
//abacaba
//me:bca
//jd:cba

//先交一发假做法

//正确做法:单调栈
posted @ 2022-07-07 23:39  Sakana~  阅读(22)  评论(0编辑  收藏  举报