1012考试

1012考试总结

T1

​ 物理题。。。。。

T2

​ 题目大意:

​ 给你\(n\)个01字符串,这个字符串可以重复无数遍:\(010 : 010010\)\(10001 : 100011000110001\),就像这样。问最多会有多少位至少两个串相等。

​ 比如:

5
001
1000
0100
010
100
输出为:4,因为第三个串和第四个串前4位相同

​ 考虑分治的做法,我们枚举位数,假设当前枚举到了第\(x\)为,我们把这一位为0的分到一起,把这一位为1的分到一起,然后递归为0的和为1的下一位,直到不能继续递归为止。

#include <bits/stdc++.h>

using namespace std;

const int N = 2e4 + 5;
int n, ans, cnt1, cnt2;
int sta1[N], sta2[N];
string ch[N];

int solve(int now, int *a, int *b, int cnt1, int cnt2) {
    if(!cnt1 && !cnt2) return 0;
    if(cnt1 + cnt2 == 1) return 0;
    int sa[N], sb[N];
    int x = 0, y = 0, res;
    for(int i = 1;i <= cnt1; i++) 
        if(ch[a[i]][now] == '0') sa[++ x] = a[i];
        else sb[++ y] = a[i];
    res = solve(now + 1, sa, sb, x, y) + 1;
    x = 0, y = 0;
    for(int i = 1;i <= cnt2; i++)
        if(ch[b[i]][now] == '0') sa[++ x] = b[i];
        else sb[++ y] = b[i];
    res = max(res, solve(now + 1, sa, sb, x, y) + 1);
    return res;
}

int main() {

    scanf("%d", &n);
    for(int i = 1;i <= n; i++) {
        cin >> ch[i]; 
        string a = ch[i]; int len = a.length();
        while(ch[i].length() + len <= 1000) ch[i] += a;
        if(ch[i][0] == '0') sta1[++ cnt1] = i;
        else sta2[++ cnt2] = i;
    }
    printf("%d", solve(1, sta1, sta2, cnt1, cnt2) - 1);
    
    fclose(stdin); fclose(stdout);
    return 0;
}

T3

​ 题目大意:

​ 给你一段序列(保证每个数两两不同),有两种操作:

​ 第一种:询问一个数\(x\)前面最小的数是多少,如果没有输出-1;

​ 第二种:将一个数\(x\)移动到队伍末尾,原来的位置空着。

​ 最后输出一个数,表示得到最后的序列后,每次移动一个数,向前向后都可以,为最少几次可以使中间没有空缺,前面和后面可以没有人,只要是长度为\(n\)的连续的一段数就行。

\(n, m <= 100000, 0 <= a[i] <= 100000000\)

​ 考场山第一问做出来了,第二问没想出来咋做,好可惜。

​ 首先离散化。

​ 开一颗线段树维护区间最小值,注意要开\(2e5 * 4\),以为最多有\(m\)次移动操作,所以原序列最多会变成\(2 * n\)那么长。询问操作直接查询区间最小值,移动操作就是将原位置的数删去,在队尾位置加上这个数。

​ 对于第二问,我们把位置上有人的记为1,把位置上没人的记为0,我们维护一个长度为\(n\)的滑动窗口,看看里边有多少个0,取最小值就是第二问答案。(Cao竟然没想出来)

#include <bits/stdc++.h>

#define ls(o) (o << 1)
#define rs(o) (o << 1 | 1)
#define mid ((l + r) >> 1)

using namespace std;

inline long long read() {
    long long s = 0, f = 1; char ch;
    while(!isdigit(ch = getchar())) (ch == '-') && (f = -f);
    for(s = ch ^ 48;isdigit(ch = getchar()); s = (s << 1) + (s << 3) + (ch ^ 48));
    return s * f;
}

const int N = 2e5 + 5, inf = 1e9;
int n, m, x, to, mo, ans, len, res;
char ch; 
int a[N], b[N], y[N], q[N], pos[N];
struct edge { int Min; } t[N << 2];

void up(int o) {
    t[o].Min = min(t[ls(o)].Min, t[rs(o)].Min);
}

void build(int o, int l, int r) {
    if(l == r) { if(l <= n) t[o].Min = a[l]; else t[o].Min = inf; return ; }
    build(ls(o), l, mid); build(rs(o), mid + 1, r);
    up(o);
}

int query(int o, int l, int r, int x, int y) {
    if(x <= l && y >= r) { return t[o].Min; }
    int tmp = inf;
    if(x <= mid) tmp = min(tmp, query(ls(o), l, mid, x, y));
    if(y > mid) tmp = min(tmp, query(rs(o), mid + 1, r, x, y));
    return tmp;
}

void change(int o, int l, int r, int x, int val) {
    if(l == r) { a[l] = val; t[o].Min = val; return ; }
    if(x <= mid) change(ls(o), l, mid, x, val);
    if(x > mid) change(rs(o), mid + 1, r, x, val);
    up(o);
}

int main() {

    n = read(); m = read();
    for(int i = 1;i <= n; i++) a[i] = b[i] = read();
    sort(b + 1, b + n + 1);
    int cnt = unique(b + 1, b + n + 1) - b - 1;
    for(int i = 1;i <= n; i++) {
        int tmp = a[i]; a[i] = lower_bound(b + 1, b + cnt + 1, a[i]) - b, y[a[i]] = tmp, pos[a[i]] = i;
    }
    len = 2 * max(n, m);
    build(1, 1, len); to = 1; mo = n;
    for(int i = 1;i <= m; i++) {
        cin >> ch; x = read();
        int li = lower_bound(b + 1, b + cnt + 1, x) - b;
        if(ch == 'A') { 
            if(pos[li] == 1) { printf("-1\n"); continue; }
            int tmp = query(1, 1, len, 1, pos[li] - 1);
            if(tmp == inf) printf("-1\n");
            else printf("%d\n", y[tmp]);
        }
        if(ch == 'M') {
            change(1, 1, len, pos[li], inf);
            mo ++; pos[li] = mo;
            change(1, 1, len, mo, li);
        }
    }
    for(int i = 1;i <= n; i++) if(a[i] == inf) res ++;
    ans = res;
    for(int i = n + 1;i <= mo; i++) {
        if(a[i - n] == inf) res --;
        if(a[i] == inf) res ++;
        ans = min(ans, res);
    }
    printf("%d", ans);

    fclose(stdin); fclose(stdout);
    return 0;
}
posted @ 2020-10-13 07:14  C锥  阅读(102)  评论(0编辑  收藏  举报