Deltix Round, Summer 2021 (open for everyone, rated, Div. 1 + Div. 2) A-D

https://codeforces.com/contest/1556

A题

给你两个数初始值为 0 0 0,可以同时加上一个数或者一个加一个减,问最少需要多少次能够达到目标值

  • 显然应该先同时加上两数平均数,然后再一个加一个减,特判相等、无解的情况即可
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 100;
const double eps = 1e-6;
int main(){
    
    
    #ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t, c, d;
    cin >> t;
    while(t--){
    
    
        cin >> c >> d;
        if(c > d) swap(c, d);
        int k = d - c;
        if(k == 0 && c == 0) cout << 0 << '\n';
        else if(k == 0) cout << 1 << '\n';
        else if(k & 1) cout << -1 << '\n';
        else{
    
    
            cout << 2 << '\n';
        }
    }
    return 0;
}

B题

给出一个数组,每次只能交换相邻的两个数,问最少多少步让这个数组相邻的数字奇偶性不同

  • 如果数组元素个数是偶数,奇数元素和偶数元素数量必须相等,此时有两种情况,分别是奇数在奇数位和奇数在偶数位;如果数组元素是奇数,奇数元素和偶数元素数量差 1 1 1,多的那个在奇数位
  • 思路就是把该放到对应位置的数字放好,也就是第一个奇数放到 1 1 1,第二个奇数放到 3 3 3,以此类推,这样做为什么是对的呢?我们考虑最后的奇数,为了用最少的步骤,他肯定要去最后面的位置,以此类推
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int MAXN = 1e6 + 100;
const double eps = 1e-6;
int a[MAXN];
int main(){
    
    
    #ifdef LOCAL
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    #endif
    ios::sync_with_stdio(false);
    cin.tie(0);
    int t, n;
    cin >> t;
    while(t--){
    
    
        cin >> n;
        int odd, even;
        int ans = 0;
        odd = even = 0;
        int l = 1;
        for(int i=1;i<=n;i++){
    
    
            cin >> a[i];
            if(a[i] & 1) odd++;
            else even++;
        }
        if(n & 1){
    
    
            if(abs(odd - even) != 1){
    
    
                cout << -1 << '\n';
                continue;
            }
            if(odd > even){
    
    
                for(int i=1;i<=n;i++){
    
    
                    if(a[i] & 1){
    
    
                        ans += abs(i - l);
                        l += 2;
                    }
                }                
            }else{
    
    
                for(int i=1;i<=n;i++){
    
    
                    if(!(a[i] & 1)){
    
    
                        ans += abs(i - l);
                        l += 2;
                    }
                }
            }
        }else{
    
    
            if(odd != even){
    
    
                cout << -1 << '\n';
                continue;
            }else{
    
    
                for(int i=1;i<=n;i++){
    
    
                    if(a[i] & 1){
    
    
                        ans += abs(i - l);
                        l += 2;
                    }
                }
                int tmp = ans;
                ans = 0;
                l = 1;
                for(int i=1;i<=n;i++){
    
    
                    if(!(a[i] & 1)){
    
    
                        ans += abs(i - l);
                        l += 2;
                    }
                }
                ans = min(ans, tmp);
            }
        }
        cout << ans << '\n';
    }
    return 0;
}

C题

  • 这个题 O ( n ) O(n) O(n)算法可以用栈来做,具体思路是可以设一个 s t a c k < p a i r < l l , l l > > stack<pair<ll,ll>> stack<pair<ll,ll>>,这样 p a i r pair pair f i r s t first first表示未匹配的左括号数量, s e c o n d second second表示并列的括号数,写出一堆问题…
  • 不过题目并没有那样出,数据仅仅到了 1 e 3 1e3 1e3,也就是可以使用 n 2 n^2 n2的算法,那么我们可以枚举每一组左括号,看这组左括号能够匹配多少个右括号,这样就省下很多麻烦,思路也变得清晰
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <map>
#include <unordered_map>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 100;
const int INF = 0x3f3f3f3f;
ll a[MAXN];
int main(){
    
    
    #ifdef LOCAL
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #endif
    ios::sync_with_stdio(false);
    int n;
    cin >> n;
    ll ans = 0;
    for(int i=1;i<=n;i++) cin >> a[i];
    for(int i=2;i<=n;i+=2){
    
    
        ll now;//当前左括号
        ll now_r;//当前之后的左括号
        now_r = 0;
        if(a[i] > a[i - 1]){
    
    
            ans += a[i - 1];
            continue;
        }else{
    
    
            now = a[i - 1] - a[i];
            ans += a[i];
        }
        for(int j=i+2;j<=n;j+=2){
    
    
            if(a[j] < a[j - 1]){
    
    
                now_r += a[j - 1] - a[j];
            }else{
    
    
                ll rest_r = a[j] - a[j - 1];
                if(rest_r < now_r){
    
    
                    now_r -= rest_r;
                }else{
    
    
                    rest_r -= now_r;
                    now_r = 0;
                    if(now < rest_r){
    
    
                        ans += now + 1;
                        break;
                    }else{
    
    
                        now -= rest_r;
                        ans += rest_r + 1;
                    }
                }
            }
        }
    }
    cout << ans;
    return 0;
}
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <map>
#include <unordered_map>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 100;
const int INF = 0x3f3f3f3f;
ll ans;
stack<pair<ll, ll> > st;
void solve(int l, int r, ll u){
    
    
    if(l > u){
    
    
        ans += u;
        st.push({
    
    l - u, 1});
    }else if(l == u){
    
    
        ans += u;
        l = st.top().first;
        r = st.top().second;
        st.pop();
        ans += r;
        st.push({
    
    l, r + 1});
    }else{
    
    
        ans += l;
        u -= l;
        l = st.top().first;     
        r = st.top().second;
        st.pop();
        ans += r;
        if(l) solve(l, r, u);
        else st.push({
    
    0, 0});
    }
}
void solve(){
    
    
    int n;
    ll u;
    cin >> n;
    st.push({
    
    0, 0});
    for(int i=1;i<=n;i++){
    
    
        cin >> u;
        if(i & 1){
    
    
            st.push({
    
    u, 0});
        }else{
    
    
            int l = st.top().first;
            int r = st.top().second;
            st.pop();
            if(l) solve(l, r, u);
            else st.push({
    
    0, 0});
        }
    }
    cout << ans;
}
int main(){
    
    
    #ifdef LOCAL
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #endif
    ios::sync_with_stdio(false);
    solve();
    return 0;
}

D题

交互题。已知数组长度 n n n,可以进行最多 2 n 2n 2n次询问,每次询问数组任意两个数之间的 o r or or或者 a n d and and,现在要求第 k k k

  • 这个题目的关键点在于我们要知道 a + b = ( a ∣ b ) + ( a & b ) a+b=(a|b)+(a\&b) a+b=(ab)+(a&b),其证明可以通过讨论四种情况来进行判断,那么一旦知道了这个结论,那么思路就不难想到,我们要对前三个数字两两进行询问它们之间的与和或,这样可得到 a 1 + a 2 , a 1 + a 3 , a 2 + a 3 a_1+a_2,a_1+a_3,a_2+a_3 a1+a2,a1+a3,a2+a3的值,那么就可以把数组的前三个元素求出来,这样往后递推询问即可得到全部数组
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <cmath>
#include <cstdio>
#include <map>
#include <unordered_map>
using namespace std;
typedef long long ll;
const int MAXN = 2e5 + 100;
const int INF = 0x3f3f3f3f;
int a[MAXN];
int Get_or(int i, int j){
    
    
    int x;
    cout << "or " << i << ' ' << j << endl;
    cin >> x;
    return x;
}
int Get_and(int i, int j){
    
    
    int x;
    cout << "and " << i << ' ' << j << endl;
    cin >> x;
    return x;
}
void Get_Finish(int k){
    
    
    cout << "finish " << a[k];
}
int main(){
    
    
    #ifdef LOCAL
        freopen("input.txt", "r", stdin);
        freopen("output.txt", "w", stdout);
    #endif
    ios::sync_with_stdio(false);
    int n, k;
    cin >> n >> k;
    int x1 = Get_and(1, 2);int x2 = Get_or(1, 2);
    int y1 = Get_and(2, 3);int y2 = Get_or(2, 3);
    int z1 = Get_and(1, 3);int z2 = Get_or(1, 3);
    a[1] = (x1 + x2 + z1 + z2 - y1 - y2) / 2;
    a[2] = (y1 + y2 - z1 - z2 + x1 + x2) / 2;
    a[3] = (y1 + y2 + z1 + z2 - x1 - x2) / 2;
    for(int i=3;i<n;i++){
    
    
        x1 = Get_and(i, i + 1);
        x2 = Get_or(i, i + 1);
        a[i + 1] = x1 + x2 - a[i];
    }
    sort(a + 1, a + 1 + n);
    Get_Finish(k);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/roadtohacker/article/details/119994780