CSP - S 题解 (伪)
user146888 · · 个人记录
说是题解,其实基本上是抄题解。
总是要找个方法复习的。
Day 1
T1 grey码
小灰(月厨特有幻视)
根据题意模拟 ,记得开unsigned long long。
code
T2 括号树
神TM洛谷两个秋令营都压到了这题,提高老师甚至想出过这个idea,然后觉得太简单,就又改难了,栈 -> nlgn,n sqrt(n)数据结构。(分块大法好)
题意
在链上时就是一个括号匹配,借此维护题目要求的sum数组。
至此可获得55分。
显然链上问题可以用DFS解决,但显然唯一的难点是回溯时需要撤销当次的操作,在操作过程中,维护一个用于进行括号匹配的栈。
code
#include<cstdio>
#include<vector>
#define ll long long
using namespace std;
const int maxn = 5e5 + 10;
vector<int> e[maxn];
int en;
ll s[maxn] , work[maxn] , sum[maxn];
void push(int x) {s[++en] = x;}
void del() {en --;}
int n;
int fa[maxn];
char ch[maxn];
void dfs(int now) {
int de = 0;
if(ch[now] == ')' && en) {
de = s[en];
work[now] = work[fa[de]] + 1;
en --;
}
if(ch[now] == '('){s[++ en] = now;}
sum[now] = sum[fa[now]] + work[now];
for(int i=0;i<e[now].size();i++) {
dfs(e[now][i]);
}
if(de) {
s[++en] = de;
} else {if(en) en--;}
}
int main() {
scanf("%d",&n);
scanf("%s",ch+1);
int x , y;
for(int i=2;i<=n;i++) {
scanf("%d",&x);
e[x].push_back(i);
fa[i] = x;
}
dfs(1);
ll ans = 0;
for(int i=1;i<=n;i++) {
ans ^= sum[i] * (1ll * i);
}
printf("%lld",ans);
return 0;
}
Day 2
T1 Emiya家的饭
关于年番 《卫宫家今天的饭》我还是看了的。花之魔术师 梅林 提供特效
然而我梅林池歪了孔明。艹
关于题目,考试时只会打暴力,还因为层数维护问题写挂了。
显然DFS会T掉,最终只能用DP+容斥,来反向处理掉这个题目。
考虑枚举被选中了比 k/2 大的食材。
改写判断条件得:
因为
有一个我无法证明其正确性的结论。最优解的最后段与其它解相比最小。利用此性质可以进一步优化。