C. Compressed Bracket Sequence
一道比较有意思的括号匹配问题,可以发现括号的数量很多,有1e9 * 1000个,所以我们放弃将括号表示出来,考虑其他方法。观察可以发现这个n很小,只有1000,可以从n下手。
可以想到 O ( n 2 ) O(n^2) O(n2)的暴力枚举起点和终点,然后计算当前起点和终点为答案贡献的合法括号数量(注意,我们统计的是包含当前起点和终点的合法括号)。
注意到只有左括号作为起点才对答案有贡献,所以我们的起点只用枚举所有的奇数位就可以。
首先我们把左端点(起点)位置的左括号数量设为begin,然后控制右端点(终点)向后走,途中遇到的未匹配的左括号数量为sum。如果遇到了右括号,那么我们首先判断sum的数量是否大于当前右括号的数量,如果大于等于,说明当前所有的右括号都与途中未匹配的左括号匹配了,无法与起点位置的左括号匹配;如果小于,说明当前位置的右括号除了与途中的左括号匹配之外,还有有一部分可以与起点位置的左括号匹配,对答案做贡献,设当前的右括号数量为p,这个贡献就是min(begin,p - sum);
有一个需要注意的地方是:如果p > sum且sum != 0,那么答案需要加1。
例如:(()()),右边的()除了自己会形成一个合法答案之外{这个自己形成的合法答案会在起点周到下标为4(下标从1开始)的位置上时才会计入答案},()()也是一个合法答案(即它会与前面已经匹配好的合法括号合并成一个新的合法括号)。
ACcode:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 100;
typedef long long ll;
typedef pair<int, int> PII;
int a[N];
void solve() {
int n;
ll ans = 0;
scanf("%d", &n);
for(int i = 1; i <= n; ++ i) scanf("%d", &a[i]);
for(int i = 1; i <= n; i += 2) {
ll sum = 0, beg = a[i];
for(int j = i + 1; j <= n; ++ j) {
if(j & 1) sum += a[j];
else {
if(sum > a[j]) {
sum -= a[j];
}
else {
if(sum != 0) ans ++;
ans += min(beg, a[j] - sum);
beg -= a[j] - sum;
sum = 0;
}
}
if(beg < 0) break;
//如果当前起点剩余未匹配的左括号数量小于0的话,说明以当前起点作为左端点的合法括号不可能存在,所以需要换一个起点。
//如果当前起点剩余未匹配的左括号数量等于0的话,后面还有可能有新的合法括号与当前起点匹配完的括号组成一个新的合法括号,例如:()()(())。
}
}
printf("%lld\n", ans);
}
int main() {
#ifndef ONLINE_JUDGE
freopen("1.in", "r", stdin);
freopen("1.out", "w", stdout);
#endif
solve();
return 0;
}
/*
5
4 1 2 3 1
(((()(()))(
*/
D - Take a Guess
预备知识:a + b = a & b + a | b
已知a1 + a2, a1 + a3, a2 + a3,那么我们就可以用2 * a1 + a2 + a3 - (a2 + a3),求出a1。
然后求出所有的a1 + ai,( 2 ≤ i ≤ n 2 \leq i \leq n 2≤i≤n),因为已知了a1,所以我们就可以求出所有的ai。
求完之后排个序就可以得到答案。
ACcode:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 100;
typedef long long ll;
typedef pair<int, int> PII;
int a[N], pp[N];
void solve() {
int n, k, res;
scanf("%d%d", &n, &k);
fflush(stdout);
int sum23 = 0;
printf("and 2 3\n");
fflush(stdout);
scanf("%d", &res);
fflush(stdout);
sum23 += res;
printf("or 2 3\n");
fflush(stdout);
scanf("%d", &res);
fflush(stdout);
sum23 += res;
for(int i = 2; i <= n; ++ i) {
printf("and 1 %d\n", i);
fflush(stdout);
scanf("%d", &res);
fflush(stdout);
pp[i] += res;
printf("or 1 %d\n", i);
fflush(stdout);
scanf("%d", &res);
fflush(stdout);
pp[i] += res;
}
a[1] = (pp[2] + pp[3] - sum23) / 2;
for(int i = 2; i <= n; ++ i) a[i] = pp[i] - a[1];
sort(a + 1, a + 1 + n);
printf("finish %d\n", a[k]);
fflush(stdout);
}
int main() {
solve();
return 0;
}
/*
a + b
b + c
a + c
*/