2019 cattle off more school third solution to a problem

2019 cattle off more school third solution to a problem

Topic Link

B.Crazy Binary String

Sequences and to maintain a prefix, the answer substring \ (2 * min (0,1) \) number.


Code

#include<bits/stdc++.h>
typedef long long ll;
const int MAXN = 1e5 + 5, MAXM = 1e5 + 5, INF = 0x3f3f3f3f, MOD = 998244353;
const ll INFL = 0x3f3f3f3f3f3f3f3f;
using namespace std;
#define lson o<<1,l,m
#define rson o<<1|1,m+1,r
#define mid l + ((r-l)>>1)
#define pb push_back
#define random(a,b) ((a)+rand()%((b)-(a)+1))
typedef double db;
int n, cnt[2], mp[MAXN << 1], delta = 100000;
char t[MAXN];
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> n;
    cin >> (t + 1);
    int sum = 0, ans = 0;
    for (int i = 1; i <= n; i++) {
        cnt[t[i] - '0']++;
        if (t[i] == '1')sum++;
        else sum--;
        if (sum == 0)ans = max(ans, i);
        if (mp[sum + delta]) {
            ans = max(ans, i - mp[sum + delta]);
        }
        else mp[sum + delta] = i;
    }
    cout << ans << ' ' << min(cnt[0], cnt[1]) * 2 << '\n';
    return 0;
}

D.Big Integer

Readily available \ (A (n-) = \ FRAC {10 ^ n--. 1} {. 9} \) , so the problem is the requirement \ (A (n) = \ frac {10 ^ n-1} {9} = 0 ( mod p) \) .
Consider \ (p! = 3 \) when there is \ ((10 ^ n--. 1) * INV (. 9) = 0 (MOD P) \) , because \ (INV (. 9)! = 0 \) , so the formula can be reduced to sub \ (^ n-10 =. 1 (mod p) \) .

Consider \ (p! = 2, p ! = 5 \) is the case, then there is \ (GCD (10, P) =. 1 \) , so \ (10 ^ {\ varphi ( p)} = 1 (modp ) \) , since \ (^ 0 = 10. 1 (mod p) \) , it is possible to know that a loop section \ (\ varphi (P). 1-P = \) . We now require a minimum loop section \ (d \) , then surely satisfy \ (d | (the p--1) \) , where we seek to enumerate direct violence on the line.

The next step is to find all \ (. 1 \ Leq I \ n-Leq,. 1 \ Leq J \ Leq m \) , satisfies \ (d | i ^ j \ ) number.
The \ (D \) is decomposed as: \ (P_1 k_1} ^ {^ {P_2 P_T K_2 ...}} ^ {K_t \) , then have to satisfy the above conditions \ (g = p_1 ^ {\ lceil \ frac {k_1} {j} \ rceil} p_2 ^ {\ lceil \ frac {k_2} {j} \ rceil} ... p_t ^ {\ lceil \ frac {k_t} {j} \ rceil} | i \) At this time \ (I \) number is \ (\ {n-FRAC {G}} \) . After the enumeration \ (j \) on the line, we only enumerate here to \ (30 \) , then bigger the value is the same.
If \ (p = 2 || p = 5 \) , the obvious answer is \ (0 \) .

Now consider \ (p = 3 \) case, for a number, if it is \ (3 \) multiple of, the number of each of its upper position and it is \ (3 \) multiples. For this problem, it is required \ (i ^ j = 0 ( mod 3) \) all \ (i, j \) number. Direct count on the line.

See detailed bar code, this problem can not put \ (9 \) about to go directly to enumerate \ (\ varphi (9p) \ ) divisor. But because modulus than the int, might burst long long.

code show as below:


Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5, INF = 1e9;
int T;
int n, m, p;
ll qp(ll a, ll b, int P) {
    ll ans = 1;
    while(b) {
        if(b & 1) ans = ans * a % P;
        a = a * a % P;
        b >>= 1;
    }
    return ans;
}
int pri[N], cnt[N], k;
void work(int x, int *a, int *b) {
    k = 0;
    for(int i = 2; 1ll * i * i <= x; i++) {
        if(x % i == 0) {
            a[++k] = i; int c = 0;
            while(x % i == 0) c++, x /= i;
            b[k] = c;
        }
    }
    if(x > 1) {
        a[++k] = x; b[k] = 1;
    }
}
int solve(int j) {
    int x = 1;
    for(int i = 1; i <= k; i++) {
        int t = (cnt[i] + j - 1) / j;
        while(t--) x *= pri[i];
    }
    return n / x;
}
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> T;
    while(T--) {
        cin >> p >> n >> m;
        if(p == 2 || p == 5) {
            cout << 0 << '\n';
            continue ;
        }
        if(p == 3) {
            cout << 1ll * m * (n / 3) << '\n';
            continue;
        }
        int phi = p - 1, d = INF;
        for(int i = 1; 1LL * i * i <= phi; i++) {
            if(phi % i == 0) {
                if(qp(10, i, p) == 1) d = min(d, i);
                if(qp(10, phi / i, p) == 1) d = min(d, phi / i);
            }
        }
        work(d, pri, cnt);
        ll ans = 0;
        for(int j = 1; j <= min(30, m); j++) ans += solve(j);
        if(m > 30) ans += 1ll * (m - 30) * solve(30);
        cout << ans << '\n';
    }
    return 0;
}

F.Planting Trees

Start writing \ (O (n ^ 3logn) \) is a two-dimensional table st, no card in the past = =
then actually direct monotonous queue on the line, the enumeration rectangular upper and lower boundaries, then enumerate the right boundary, maintaining the minimum feasible left boundary. Since the left boundary is nondecreasing complicated than \ (O (n-^. 3) \) . Come true with pointers to record on the line.
code show as below:


Code

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N = 505, INF = 1e9;
    int T;
    int n, m;
    int a[N][N];
    int cmx[N], cmn[N];
    int q1[N], q2[N];
    int l1, r1, l2, r2;
    int main() {
        ios::sync_with_stdio(false); cin.tie(0);
        cin >> T;
        while(T--) {
            cin >> n >> m;
            int ans = 0;
            for(int i = 1; i <= n; i++) for(int j = 1; j <= n; j++) cin >> a[i][j];
            for(int i = 1; i <= n; i++) {
                for(int j = 1; j <= n; j++) cmx[j] = 0, cmn[j] = INF;
                for(int j = i; j <= n; j++) {
                    for(int k = 1; k <= n; k++) cmx[k] = max(cmx[k], a[j][k]), cmn[k] = min(cmn[k], a[j][k]);
                    l1 = l2 = 1; r1 = r2 = 0;
                    int p = 1;
                    for(int k = 1; k <= n; k++) {
                        while(l1 <= r1 && cmx[q1[r1]] <= cmx[k]) r1--;
                        q1[++r1] = k;
                        while(l2 <= r2 && cmn[q2[r2]] >= cmn[k]) r2--;
                        q2[++r2] = k;
                        while(cmx[q1[l1]] - cmn[q2[l2]] > m) {
                            p++;
                            if(l1 <= r1 && q1[l1] < p) l1++;
                            if(l2 <= r2 && q2[l2] < p) l2++;
                            if(p > k) break;
                        }
                        ans = max(ans, (j - i + 1) * (k - p + 1));
                    }
                }
            }
            cout << ans << '\n';
        }
        return 0;
    }

G.Removing Stones

Win condition can be found as follows: For a period of interval is, \ (sum_r-sum_ {}. 1-L> = 2 * MX \) .
A maximum interval section can be divided into two parts, so that the partition can be considered, for the position of the maximum of the two divided sections, small enumeration range that interval, the interval in which the other two points on the line (Hirakata For a large range of complexity may be reduced to O (n ^ 2) instead of \ (O (nlogn) \) ).
Complexity \ (O (nlognlogn) \) , seeking the most st position also needed a table, or you'll T.


Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 300005;
int T;
int n;
int a[N];
ll sum[N];
ll ans;
int f[N][19], pos[N][19];
int lg[N];
void init() {
    for(int i = 1; i <= n; i++) f[i][0] = a[i], pos[i][0] = i;
    for(int j = 1; j <= 18; j++) {
        for(int i = 1; i + (1 << j) - 1 <= n; i++) {
            if(f[i][j - 1] > f[i + (1 << (j - 1))][j - 1]) {
                pos[i][j] = pos[i][j - 1];
            } else pos[i][j] = pos[i + (1 << (j - 1))][j - 1];
            f[i][j] = max(f[i][j - 1], f[i + (1 << (j - 1))][j - 1]) ;
        }
    }
}
int query(int l, int r) {
    int k = lg[r - l + 1];
    if(f[l][k] > f[r - (1 << k) + 1][k]) return pos[l][k];
    return pos[r - (1 << k) + 1][k];
}
void solve(int l, int r) {
    if(r - l <= 0) return;
    if(r - l == 1) {
        if(a[l] == a[r]) ans++;
        return;
    }
    int k = query(l, r);
    int mx = a[k];
    if(k - l < r - k) {
        for(int L = l; L <= k; L++) {
            int LL = k, RR = r + 1, mid;
            while(LL < RR) {
                mid = (LL + RR) >> 1;
                if(sum[mid] - sum[L - 1] - mx >= mx) RR = mid;
                else LL = mid + 1;
            }
            ans += (r - LL + 1);
        }
    } else {
        for(int R = k; R <= r; R++) {
            int LL = l ,RR = k + 1, mid;
            while(LL < RR) {
                mid = (LL + RR) >> 1;
                if(sum[R] - sum[mid - 1] - mx >= mx) LL = mid + 1;
                else RR = mid;
            }
            ans += (LL - l);
        }
    }
    solve(l, k - 1); solve(k + 1, r);
}
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    for(int i = 2; i < N; i++) lg[i] = lg[i >> 1] + 1;
    cin >> T;
    while(T--) {
        cin >> n; ans = 0;
        for(int i = 1; i <= n; i++) cin >> a[i], sum[i] = sum[i - 1] + a[i];
        init();
        solve(1, n);
        cout << ans << '\n';
    }
    return 0;
}

H.Magic Line

By x, y sort, after considering a slightly inclined straight line.


Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1005, INF = 1e8;
int T;
struct point{
    int x, y;
    bool operator < (const point &A)const {
        if(x == A.x) return y < A.y;
        return x < A.x;
    }
}a[N];
int n;
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> T;
    while(T--) {
        cin >> n;
        for(int i = 1; i <= n; i++) cin >> a[i].x >> a[i].y;
        sort(a + 1, a + n + 1);
        if(a[n / 2].x == a[n / 2 + 1].x) {
            cout << a[n / 2].x - 1 << ' ' << a[n / 2].y + INF << ' ' << a[n / 2 + 1].x + 1 << ' ' << a[n / 2 + 1].y - INF << '\n';
        } else {
            cout << a[n / 2].x << ' ' << -INF << ' ' << a[n / 2 + 1].x << ' ' << INF << '\n';
        }
    }
    return 0;
}

I.Median

There is a conclusion that \ (a_i \) must be equal to affect one of its medians.
Proof, then you can push it, will eventually find that \ (a_i \) or greater than equal to the number three, less than or equal to, apparently taking tantamount feasible.
After proceeds \ (DP \) , for which a current \ (I \) , by (i-2, i-1 \) \ transferred from, let \ (dp [i] [j ] [k] \) represents \ (I \) bit associated with the first \ (j + 1 \) sized digits, \ (. 1-I \) bit associated with the section \ (k + 1 \) sized bits number, and finally from the \ (dp [i-1] [k] [l] \) transfer over.
\ (v [i] [j ] \) is stored is the effect of \ (I \) number of \ (j + 1 \) sized digits.
When the transfer is recorded at the precursor on the line.
Legitimacy determining when a note is legitimate front in this state, the other is filled, then the current number of bits equal to meet the \ (I-B_. 1} {\) (code inside the subscripts \ (i-1 \ ) actually \ (i-2 \))
Code is as follows:


Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e5 + 5;
int T;
int b[N], a[N];
int dp[N][3][3], v[N][3], pre[N][3][3];
int n;
int med(int x, int y, int z) {
    int tmp[3];
    tmp[0] = x, tmp[1] = y, tmp[2] = z;
    sort(tmp, tmp + 3);
    return tmp[1];
}
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> T;
    while(T--) {
        for(int i = 1; i <= n; i++)
            for(int j = 0; j < 3; j++)
                for(int k = 0; k < 3; k++)
                    dp[i][j][k] = pre[i][j][k] = 0;
        cin >> n;
        for(int i = 2; i < n; i++) cin >> b[i];
        b[0] = b[1] = b[2];
        b[n + 1] = b[n] = b[n - 1];
        for(int i = 1; i <= n; i++) {
            for(int j = 0; j < 3; j++) {
                v[i][j] = b[i + j - 1];
            }
            sort(v[i], v[i] + 3);
        }
        for(int i = 1; i <= 2; i++)
            for(int j = 0; j < 3; j++)
                for(int k = 0; k < 3; k++)
                    dp[i][j][k] = 1;
        for(int i = 3; i <= n; i++) {
            for(int j = 0; j < 3; j++) {
                for(int k = 0; k < 3; k++) {
                    for(int l = 0; l < 3; l++) {
                        if(!dp[i - 1][k][l]) continue;
                        if(med(v[i - 2][l], v[i - 1][k], v[i][j]) != b[i - 1]) continue;
                        dp[i][j][k] = 1;
                        pre[i][j][k] = l;
                    }
                }
            }
        }
        int x = -1, y = -1;
        for(int i = 0; i < 3; i++) for(int j = 0; j < 3; j++) {
            if(dp[n][i][j]) {
                x = i, y = j;
                break ;
            }
        }
        if(x == -1 || y == -1) {
            cout << -1 << '\n';
            continue ;
        }
        for(int i = n; i >= 1; i--) {
            a[i] = v[i][x];
            x = pre[i][x][y];
            swap(x, y);
        }
        for(int i = 1; i <= n; i++) cout << a[i] << ' ' ;
        cout << '\n';
    }
    return 0;
}

J.LRU management

Direct simulation, a little more detail. . .


Code

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 500005, M = 15;
int T;
char s[M];
int st, ed, sz;
int q, m;
int L[N], R[N], data[N];
int trie[N * 10], pos[N * 10], ch[N * 10][10], tot;
void trieInsert(int it, char *s){
    assert(strlen(s) <= 10);
    int p = 0;
    for (int i = 0; s[i]; i++){
        int &t = ch[p][s[i] - '0'];
        if (!t) t = ++tot; p = t;
    }
    pos[trie[it] = p] = it;
}

int trieFind(char *s){
    int p = 0;
    for (int i = 0; s[i]; i++){
        p = ch[p][s[i] - '0'];
        if(!p) return 0;
    }
    return pos[p];
}
void Erase(int x){
    int pre = L[x], succ = R[x];
    if (pre) R[pre] = succ;
    if (succ) L[succ] = pre;
    data[x] = L[x] = R[x] = 0;
    if (x == st) st = succ;
    if (x == ed) ed = pre;
    --sz;
}

void Insert(int x, int v){
    data[x] = v;
    if (!st) st = ed = x;
    else L[R[ed] = x] = ed, ed = x;
    ++sz;
}
int main() {
    ios::sync_with_stdio(false); cin.tie(0);
    cin >> T;
    while(T--) {
        st = ed = sz = 0;
        pos[tot = 0] = 0;
        cin >> q >> m;
        int num = 0;
        while(q--) {
            int op, v;
            cin >> op >> s + 1 >> v;
            int it = trieFind(s + 1);
            if(op == 1) {
                if(!it || (v == 1 && !R[it]) || (v == -1 && !L[it])) cout << "Invalid" << '\n';
                else {
                    if(v == -1) it = L[it];
                    if(v == 1) it = R[it];
                    cout << data[it] << '\n';
                }
            } else {
                if(it) {
                    v = data[it];
                    Erase(it);
                }
                if(sz == m) pos[trie[st]] = 0, Erase(st);
                Insert(++num, v);
                trieInsert(num, s + 1);
                cout << v << '\n';
            }
        }
        for(int i = 0; i <= tot; i++) {
            for(int j = 0; j < 10; j++) ch[i][j] = 0;
            pos[i] = trie[i] = 0;
        }
        while(st) Erase(st);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/heyuhhh/p/11260357.html