11月14日
做了19年cspT2,如果两个括号间的正反括号数相等,不一定合法()))(((),不过树上操作递归的思路没错。
11.15 括号序列 思考过程
首先可以想到要计算每个点的贡献,那就先考虑通过栈的方法能匹配的第一个位置,贡献+1。
如果更之前也可以匹配的话,考虑到不是第一个匹配的,那就肯定是由几个匹配括号组成的()(())。
显然之前的匹配已经被计算过,事实上第一个匹配位置之前的贡献都可以和新括号产生新序列,得到方程gx[d]=gx[pre]+1。(贡献gx)利用树形结构进行类似深搜过程的处理即可。
#include<bits/stdc++.h>
using namespace std;
const long long M=5e5+10;
struct bian{
long long to,next;
}bi[M];
long long fat[M],kh[M],gx[M],sum[M],n,head[M],cnt,ans;
char c;
stack <long long> ch;
void pb(long long a,long long b)
{
bi[++cnt].to=b;
bi[cnt].next=head[a];
head[a]=cnt;
}
void dfs(long long fa)
{
long long o,re;
if(kh[fa]==-1 && kh[ch.top()]==1)
{
re=ch.top();
o=1;
gx[fa]=gx[fat[ch.top()]]+1;
ch.pop();
}
else
{
ch.push(fa);
o=-1;
}
sum[fa]+=gx[fa];
for(long long i=head[fa];i!=-1;i=bi[i].next)
{
long long so=bi[i].to;
sum[so]=sum[fa];
dfs(so);
}
if(o==-1) ch.pop();
else ch.push(re);
}
int main()
{
cin>>n;
memset(head,0xff,sizeof(head));
getchar();
for(long long i=1;i<=n;i++)
{
c=getchar();
if(c=='(') kh[i]=1;
else kh[i]=-1;
}
for(long long i=2;i<=n;i++)
{
scanf("%lld",&fat[i]);
pb(fat[i],i);
}
ch.push(0);
dfs(1);
for(long long i=1;i<=n;i++)
{
ans=ans^(sum[i]*i);
}
cout<<ans;
return 0;
}
11.16 晚自习学习了分层图
因为可能根本用不到所有的限制条件就能到达终点,比如模板题上的不需要用到所有路径减半卡就能到终点,所以答案是每一层的最小值。自己摸索出的建图,很有成就感阿。
11.23 打出了A*算法
题目还是八数码,但用A*打出来了,300ms变成10ms。估价函数记得要加上走过的距离才是预估距离。算法的核心是每次都更新最有希望的状态,但更新完后就删除初状态,每次都再去找最有希望的,保证了算法的正确性。如果存在绕路的情况,那么一定从别的更近的更新。
12.16 dp练习开始
什么是状态?什么需要设到状态里?状态必须能完全的刻画一种情况,状态的值是要全部保留而不是取最大存起来的,是转移方程中必须的。
2022.1.7 树链剖分复杂度
先套一个线段树的log,由于每走一个轻链siz至少少一半,所以最多走logn个轻链;由于每两个轻链间最多一个重链,所以最多最多logn个重链。
1.23 今天改了好久的p2055,人家输入的数据就没人需要住宿,bfs根本不会跑,答案是0。教训是以后统计答案的步骤要单独拎出来
1.24 今天做最长不下降序列,一个是j<i不能等于,还有是a[j]<=a[i],不下降可以等于。弄混了一次结果只是改了一部分。记住代码牵一发而动全身的特点。还有就是特判长度为1,一般这都是极端情况,记得考虑最简单的情况
1.25上午,这会儿写完了脏毛巾什么的问题,也是24题中的。最开始误以为要把每天的结束点和汇连边,但实际上汇的操作很多,应该把操作比较少的起始点和汇连边,再通过直接给结束点发脏毛巾的方法分配毛巾,脏毛巾肯定能产生这么多,干净的从哪里弄就和他没关系了。记住,不用再有操作的才往汇点流。还有,攒着干净毛巾不能简单从i到i+1,当i=n时又流到别的结束点了,分层图尤其注意这一点。
1.26上午思考有感
最大费用最大流和最大流一样,引入了反向边,这就实现了后悔的机制,所以最大费用就是最大的总费用,而不是把两遍找到的最大费用简单加起来。还有,费用不止是价格什么的,更体现一种距离的思想,所以关于距离的问题多想费用流。
今天上午比较浮躁,又体会了小错误一堆的感觉。网络流图和普通图不一样,很复杂。遇到要输出路径的题就容易弄乱。先要理清有哪些边,这些边各自跑完之后都是什么情况。特判真是想不到。
2.3
最近有在做题,但是总是犯小错误。今天做的p1486,对平衡树的理解不够,错认为左节点是最小的,右节点是最大的,结果出了错。还有就是删除子树不改siz,没有注意是否是小于等于还是小于。实在做不出来的时候可以和别人的题解原样对应。没有之前那种打完一遍过的感觉了。树链剖分很规范很标准,网络流主要在建图,现在又面临着改题难的困境。
3.3
时不我待
线性结构,肯定不是从左或从右有简单的最优贪心策略。比如卡牌游戏,就需要先找出“最左”的策略,再向右“推进”。再比如12链找和为k的子串,也是看到了两边推进和奇偶性的关系。还有那个回文数(csp),也是两端推进的思想。
树形结构,无根化有根,比如at4380,枚举每一个点在每一个地方作为根,就简单了。
3.9
at4502
想法和答案有一些接近,但是只能二分。因为如果等进位到头了再填字母的话相当于白白浪费了很多字典序,第一个字母没有必要这么快更新的。
3.11
at5696
这种题的题解很少,所有的题解都在考虑从后往前的枚举法。这是一种正确的做法,但是不能用bitset。我挣扎了好久才发现需要从前往后,从后往前只能找出构造方法。
3.29
上个星期做的支配,一是没有读懂题,以为边加进去就出不来。二是没有标记这个点是否修改过。
周末做的题,需要统计l到r中小于l的数,什么二维数点二维思想都只是知识点而已。我们只要运用前缀和思想,l到r转化为1-r减去1-l,一个一个往上加,用区间数据结构维护,就好了。
4.1
2020省选幸运数字
1.把条件拆解成区间
2.(重要)根据题目要求,只要最靠近0的。所以,每个区间只取:在区间里且最靠近0的,不在区间里且最靠近0的。
3.只需要最后一次更新,用差分,不需要上线段树
4.11
分层图小练习,虽然一眼看出正解但是第一次是没有把起点的汉堡和可乐考虑进去,第二次是没建双向边,第三次双向边建错,要按照定义,不是简单反向建一个
4.13
差分约束系统虽然是xi-xj,但是我们把p4578里的列的贡献取成“让这一列都减少了xj”,就可以用-号了
5.6
树上dp求直径,由于每个节点保存的都是最大和次大距离,所以一个点只能管两段都在自己子树里的链,所以每个点都要和答案比大小。