上蓝场,当然要纪念一下。
做的太慢了。 1 1 1 分钟的题搞了 3 3 3 分钟。
给一个数字串,求这个数字串中任意一个是质数的子序列。
13 13 13 是质数, 31 31 31 也是质数。
所以答案肯定可以是 13 13 13 或 31 31 31。
直接看一下顺序就可以了。
int bucket[11];
repn(i, 0, s.length(), 1){
bucket[s[i] - '0'] = i;
}
if(bucket[1] < bucket[3]) cout << 13 << endl;
else cout << 31 << endl;
出题者已经很仁慈了,放过了 O ( n 2 ) O(n^2) O(n2) 算法。
给两个 01 串 s s s 和 t t t,给定操作如下:
问能否进行一次操作使得 s s s 变成 t t t。
保证 s 1 = t 1 = 0 , s n = t n = 1 s_1=t_1=0, s_n=t_n=1 s1=t1=0,sn=tn=1。
设 d i d_i di 为能否只操作 [ 1 , i ] [1,i] [1,i] 以内的数,让 s 1.. i = t 1.. i s_{1..i}=t_{1..i} s1..i=t1..i。
就显然了。
结论:当且仅当存在 i i i,使得 s i = 0 s_i=0 si=0 且 s i + 1 = 1 s_{i+1}=1 si+1=1( t t t 同理),问题有解。
请自行证明。
赛时只写了 Solution 1。
dp[0] = 1;
rep(i, 1, s.length(), 1){
pre(j, i, 1, 1){
if(s[i - 1] == s[j - 1] && t[i - 1] == t[j - 1] && s[i - 1] == t[i - 1])
dp[i] += dp[j - 1];
}
}
cout << (dp[s.length()] ? "YES" : "NO") << endl;
大水题。
有一个串 s s s,每个字符 s i s_i si 代表一个操作:
+
:在序列尾部(初始为空)加入任意整数。-
:删除序列尾部的数。0/1
:当 s i s_i si 为 1
,序列非降;否则,序列不非降。问 s s s 是否可能存在。
显然,有序的数列删去还是有序,无序的数列加上还是无序。
直接用一个栈维护这个过程就行了。
repn(i, 0, s.length(), 1){
if(s[i] == '+'){
if(st.empty() || st.top() != 1)
st.push(2);
else
st.push(1);
}
else if(s[i] == '-'){
if(st.empty()){
cout << "NO" << endl;
return;
}
st.pop();
}
else if(s[i] == '0'){
if(st.size() < 2 || st.top() == 0){
cout << "NO" << endl;
return;
}
st.pop(); st.push(1);
}
else{
if(!st.empty() && st.top() == 1){
cout << "NO" << endl;
return;
}
int cnt = 0;
while(st.size() && st.top() != 0){
st.pop(); cnt++;
}
while(cnt--) st.push(0);
}
}
cout << "YES" << endl;
好题。
将一个数列通过以下操作排序:
求最小的操作数。
以下结论请自行证明。
显然,如果将 [ l , r ] [l,r] [l,r] 乘上一个相当大的数 k k k, k 2 k^2 k2, k 3 k^3 k3,那么整个数列就变成了一个 k k k 进制数。
这样,只需找到连续的上升和下降子段就可以了。
int a[n + 1], pre[n + 1], nxt[n + 1];
arrin<int>(a + 1, a + n + 1);
pre[0] = 0, pre[1] = 1, nxt[n] = 0;
rep(i, 2, n, 1){
pre[i] = pre[i - 1];
if(a[i] >= a[i - 1]) pre[i]++;
}
pre(i, n - 1, 1, 1){
nxt[i] = nxt[i + 1];
if(a[i] >= a[i + 1]) nxt[i]++;
}
int minv = MAXN;
rep(i, 1, n, 1){
minv = min(minv, pre[i - 1] + nxt[i]);
}
cout << minv << endl;