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
"); continue; }
int tmp = query(1, 1, len, 1, pos[li] - 1);
if(tmp == inf) printf("-1
");
else printf("%d
", 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;
}