Code works round #756 (Div. 3)

Code works round #756 (Div. 3)

[1611A]. Make Even

  • Idea: there are only four cases. If the last person is even, you need to 0 0 0 times; Otherwise, if the first bit is even, just reverse the whole, and 1 1 Once; Otherwise, if a bit in the middle is even, first reverse to the first bit, and then turn to the last bit 2 2 2 times; Otherwise, there is no solution, that is, all bits are odd.
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
#define db double
#define VI vector<int>
#define PII pair<int, int>
const db Pi = 3.141592653589793;
const int INF = 0x7fffffff;
const int N = 1e5 + 5;
const db eps = 1e-10;
int cas, ans;
string s;
bool checkeven(int x){
    if((s[x] - '0') % 2 == 0) return 1;
    else return 0;
}
int main(){
    cin >> cas;
    while(cas--){
        cin >> s;
        if(checkeven(s.size() - 1)) ans = 0;
        else if(checkeven(0)) ans = 1;
        else{
            int ok = 0;
            rep(i, 0, (int)s.size() - 1){
                if(checkeven(i)){
                    ok = 1;
                    break;
                }
            }
            ans = (ok ? 2 : -1);
        }
        cout << ans << endl;
    }
}

[1611B]. Team Composition: Programmers and Mathematicians

  • Idea: might as well set a ≤ b a\le b a ≤ b, otherwise exchange. Will all s u m = a + b sum=a+b sum=a+b is divided into four parts (the surplus is ignored, and it will not form a team anyway). Consider a a a number occupied.

    1. if a ≤ s u m 4 a\le \dfrac{sum}{4} a ≤ 4sum, then each a a a corresponds to (as shown in the figure, in the same column) 3 3 3 b b b. Last superfluous b b b no one is paired. At this time, the number of teams is a a a.

      bbbbb
      bbbbb
      bbbbb
      aaaab
    2. if s u m 4 < a ≤ s u m 2 \dfrac{sum}{4}<a\le\dfrac{sum}{2} 4sum < a ≤ 2sum, then each column meets the requirements, which is 2 2 2 a a a, 2 2 2 b b b or 1 1 1 a a a, 3 3 3 b b b. At this time, the number of teams is a + b 4 \dfrac{a+b}{4} 4a+b​.

      bbbbb
      bbbbb
      aaaab
      aaaaa

So the answer is a a a and a + b 4 \dfrac{a+b}{4} 4a+b , whichever is smaller.

#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
#define db double
#define VI vector<int>
#define PII pair<int, int>
const db Pi = 3.141592653589793;
const int INF = 0x7fffffff;
const int N = 1e5 + 5;
const db eps = 1e-10;
int cas, n, a, b, c, ans;
int main(){
    cin >> cas;
    while(cas--){
        cin >> a >> b;
        if(a > b) swap(a, b);
        cout << min(a, (a + b) / 4) << endl;
    }
}

[1611C]. Polycarp Recovers the Permutation

  • Idea:
    1. First check no solution: because p p The p sequence is 1 ∼ n 1\sim n The arrangement of 1 ∼ n, so n n n is the maximum value, which must be the last number left, that is, it can only be arranged to a a a both ends of the sequence. So if a a Both ends of a sequence are not n n n. There must be no solution.
    2. Secondly, restore p p p sequence. Just be right a a a sequence is the reverse process, that is, select the larger numbers on both sides each time and insert them p p The p sequence corresponds to the left / right end. Here you can directly use the double ended queue deque
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
#define db double
#define VI vector<int>
#define PII pair<int, int>
const db Pi = 3.141592653589793;
const int INF = 0x7fffffff;
const int N = 2e5 + 5;
const db eps = 1e-10;
int cas, n, a[N];
int l, r;
deque<int> p;
int main(){
    cin >> cas;
    while(cas--){
        cin >> n;
        rep(i, 1, n) cin >> a[i];
        if(a[1] != n && a[n] != n) puts("-1");
        else{
            l = (a[1] == n ? 2 : 1), r = (a[n] == n ? n - 1 : n);
            p.clear();
            p.push_back(n);
            while(l < r){
                if(a[l] > a[r]) p.push_front(a[l++]);
                else p.push_back(a[r--]);
            }
            if(l == r) p.push_back(a[l]);
            while(p.size()){
                cout << p.front() << " ";
                p.pop_front();
            }
            cout << endl;
        }
    }
}

[1611D]. Weights Assignment For Tree Edges

  • Idea: Requirements d i s t [ p i ] < d i s t [ p i + 1 ] dist[p_i]<dist[p_{i+1}] dist[pi] < dist[pi + 1], construct d i s t [ p i ] = i dist[p_i]=i dist[pi​]=i.
    1. First, judge whether there is a solution: it is required that each node d i s t dist dist is greater than that of its ancestors d i s t dist dist. From root node d f s dfs Just search through dfs.
    2. Direct construction: for each node, its own structure has been constructed d i s t dist dist and its parent node d i s t dist dist, this side is the subtraction of two values.
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
#define db double
#define VI vector<int>
#define PII pair<int, int>
const db Pi = 3.141592653589793;
const int INF = 0x7fffffff;
const int N = 2e5 + 5;
const db eps = 1e-10;
int cas, n, root, dist[N], pre[N], ans[N];
VI nxt[N];
bool dfs(int root, int rank){
    for(auto i : nxt[root]){
        if(dist[i] <= rank) return 0;
        if(!dfs(i, dist[i])) return 0;
    }
    return 1;
}
int main(){
    cin >> cas;
    while(cas--){
        cin >> n;
        rep(i, 1, n) nxt[i].clear();
        rep(i, 1, n){
            cin >> pre[i];
            if(pre[i] == i) root = i;
            else nxt[pre[i]].push_back(i);
        }
        rep(i, 1, n){
            int x; cin >> x;
            dist[x] = i;
        }
        if(!dfs(root, dist[root])) puts("-1");
        else{
            rep(i, 1, n) cout << dist[i] - dist[pre[i]] << " ";
            cout << endl;
        }
    }
}

[1611E1]. Escape The Maze (easy version)

  • A tree, V V V starts at the root node, and some others start at different nodes x i x_i xi​. Each time, each person can move to an adjacent node or not. ask V V Can V reach a leaf node without meeting others?

  • Idea: for a node a a a. If V V V can arrive before others a a a. Equivalent to a a a the distance from the root node is less than a a a distance to the nearest node with others. The question is whether there are nodes a a a such leaf node.

    1. Simple idea: you can query the distance from each node to the root node and to all nodes x i x_i xi , the shortest distance, just compare the size. But the complexity is O ( n k ) O(nk) O(nk), need to be optimized.

    2. Optimize: find all points( x i x_i xi (and root node) b f s bfs bfs searches for the shortest distance. As long as it encounters the leaf node that the root node arrives first, this leaf is the feasible solution.

      In fact, it is a multi-source bfs, but I didn't expect it before

//Multi source bfs
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
#define db double
#define VI vector<int>
#define PII pair<int, int>
const db Pi = 3.141592653589793;
const int INF = 0x7fffffff;
const int N = 2e5 + 5;
const db eps = 1e-10;
int cas, n, k;
int fr[N], dep[N], vis[N], minfr[N];
VI edge[N];
queue<PII> q;  //The first value of PII is stored in the point, and the second value is stored in the type of point from (friend - 2 or root node - 1)
bool bfs(){
    memset(vis, 0, sizeof(vis));
    rep(i, 1, k){  //Be sure to enter your friends first
        vis[fr[i]] = 1;
        q.push({fr[i], 0});
    }
    vis[1] = 1;  //Reentry root node
    q.push({1, 1});
    while(q.size()){
        PII tmp = q.front(); q.pop();
        int now = tmp.first;
        if(now != 1 && edge[now].size() == 1 && tmp.second == 1) return 1;  //find
        for(auto i : edge[now]){
            if(vis[i]) continue;
            vis[i] = 1;
            q.push({i, tmp.second});
        }
    }
    return 0;
}
int main(){
    // freopen("1.in","r",stdin);
    cin >> cas;
    while(cas--){
        cin >> n >> k;
        rep(i, 1, k) cin >> fr[i];
        rep(i, 1, n) edge[i].clear();
        rep(i, 1, n - 1){
            int x, y; cin >> x >> y;
            edge[x].push_back(y), edge[y].push_back(x);
        }
        while(q.size()) q.pop();
        puts(bfs() ? "YES" : "NO");
    }
}

[1611E2]. Escape The Maze (hard version)

  • At least a few people need to be retained to ensure that they will be stopped V V V reaches the leaf node.
  • Idea: actually, it's really useful to ask several people. So how do you decide it's useful, when V V V goes to a point a a a find someone else has arrived a a a, then this person is useful. Just save all the useful people.
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
#define db double
#define VI vector<int>
#define PII pair<int, int>
const db Pi = 3.141592653589793;
const int INF = 0x7fffffff;
const int N = 2e5 + 5;
const db eps = 1e-10;
int cas, n, k;
int fr[N], dep[N], vis[N], minfr[N], from[N];  //From which point does the save come from
VI edge[N];
queue<int> q;
set<int> st;
int bfs(){
    memset(vis, 0, sizeof(vis));
    rep(i, 1, k){  //First in friend
        vis[fr[i]] = 1, from[fr[i]] = fr[i];
        q.push(fr[i]);
    }
    vis[1] = 1, from[1] = 1;  //Reentry root node
    q.push(1);
    while(q.size()){
        int now = q.front(); q.pop();
        if(now != 1 && edge[now].size() == 1 && from[now] == 1) return -1;
        for(auto i : edge[now]){
            if(vis[i]){
                if(from[now] == 1 && from[i] != 1) st.insert(from[i]);  //From the root node to a node where a friend has been
                continue;
            }
            vis[i] = 1, from[i] = from[now];
            q.push(i);
        }
    }
    return st.size();
}
int main(){
    // freopen("1.in","r",stdin);
    cin >> cas;
    while(cas--){
        cin >> n >> k;
        rep(i, 1, k) cin >> fr[i];
        rep(i, 1, n) edge[i].clear();
        rep(i, 1, n - 1){
            int x, y; cin >> x >> y;
            edge[x].push_back(y), edge[y].push_back(x);
        }
        while(q.size()) q.pop();
        st.clear();
        printf("%d\n", bfs());
    }
}

[1611F]. ATM and Students

For maintaining a continuous section to meet the requirements, of course, think of double pointers. But I always wanted to fix the right endpoint and move the left endpoint. I found it difficult to do so.

  • Idea: you should fix the left endpoint and keep looking for the right endpoint (because you need to ensure each endpoint) ( l , r ) (l,r) (l,r) all meet the conditions, so the right endpoint needs to look from small to large (check update every time).
    1. When the left endpoint is fixed, the right endpoint is updated so that it can no longer be added, and the record is compared.
    2. Update the left endpoint again, and then traverse.
#include<bits/stdc++.h>
using namespace std;
#define rep(i, a, b) for(int i = (a); i <= (b); i++)
#define per(i, a, b) for(int i = (a); i >= (b); i--)
#define ll long long
#define db double
#define VI vector<int>
#define PII pair<int, int>
const db Pi = 3.141592653589793;
const int INF = 0x7fffffff;
const int N = 2e5 + 5;
const db eps = 1e-10;
int cas, n, ansl, ansr, maxn;
ll now, a[N], s;
int main(){
    cin >> cas;
    while(cas--){
        cin >> n >> s;
        rep(i, 1, n) cin >> a[i];
        int t = 1;
        while(s + a[t] < 0) t++;
        ansl = ansr = 0, maxn = 0;
        now = a[t];
        for(int l = t, r = t; l <= n; l++){
            while(r + 1 <= n && s + now + a[r + 1] >= 0) now += a[++r];
            if(s + now >= 0 && maxn < r - l + 1){
                ansr = r, ansl = l;
                maxn = r - l + 1;
            }
            now -= a[l];
        }
        if(maxn <= 0) puts("-1");
        else cout << ansl << " " << ansr << endl;
    }
}

Tags: Algorithm Math

Posted on Sun, 28 Nov 2021 06:17:13 -0500 by coldkill