2018/2/23
T1 Christmas
打的是分块,数据比较弱,暴力卡卡常数都可过
有复杂度保证的分块就是先对每一个块排序,然后如果是区间加的操作的话,直接打标记,然后如果是Max操作的话,就是在块里二分出来操作对应的区间,设这个区间的有端点是r,因为每一次操作都会导致这个块里[1,r]范围内的数大小相同,那么之后的取max操作对他们的影响是相同的,所以可以发现这个r是单调递增的,那么就可以直接每个块里在额外维护一个r,mm,分别表示右端点和上一回取 max 的数是什么好了,然后统计变化数的话,加法好弄,取max的话就是在每一个右端点的位置+1,在维护一个pos数组,表示i在块中排完序后的位置,在查询变化数的时候,暴力扫一遍他所在的块在加上标记就好了
T2 Magic
网络流,两种做法
1.最小割,把一个点周围的点按照a从大到小排序,记为a[i]->a[j],那么对于每一个点新建一个点,想它后面的点连一条流量是a[j],向i这个点连一条inf的边,如果i==1,那么连S->a[i]这个点,流量是a[i]。 然后在对于每一个表示b的真点,连i->T,流量是b[i];
然后跑最小割就行了
2,最大权闭合子图,还是排好序后,每一个点的点权是a[i]-a[i+1]; b对应的点的权值是-b[i] 然后转化成最小割就行了
PS: 这种点之间的关系可以有顺序的,建出来的图大概都是类似于一条链的,然后从开头到结束就能把他们之间的顺次关系表示出来
T3 Tree
静态的话就是用倍增来找到中点,然后通过两次DP,找到每一个点的在不同子树里的最大值 (mx1),次大值(mx2),以及第三大值(mx3),到子树外的最大值(mx4),以及最大,次大分别从那个儿子转移过来。 假设现在询问 x,y,且 dis ( x , lca ) > dis ( y , lca ); 那么首先可以分别用x,y的最大值更新答案,然后用lca的子树外最大值跟新答案,如果 lca 的最大值,不是从x或y所在的子树转移过来,那么就用 lca 的最大值更新答案,否此依次下推。 然后考虑x到lca路径上的贡献,先不考虑最大值从x这棵子树转移过来的情况,那么那么路径上的点 t 的贡献就是 dep[x] - dep[t] + mx1[t]. 然后树链剖分就好了,然后考虑 x 的影响,如果 t 的最大值是从 x 转移过来的,那么这条路径上深度比 t 大的点的mx1都是从 x 转移过来的,然后倍增到这个位置,分别树链剖分维护就好了。
动态的话,就是用LCT 维护这个Splay子树中的深度最小点,深度最大的点,分别到这棵子树中所有点的最大距离(包括虚儿子),深度最大是为了换根是的反转操作。 然后在更替虚子树信息的时候,因为 max 没有可加性,所以开一个堆来维护虚子树信息。
最最值得注意的是pushup
在维护这个两个信息的时候是有顺序的,以mx1为例,mx1是到深度最小的点,那他首先可以有已有的答案更新,就是ch[0]->mx1, 然后剩下的就是从虚子树里,和深度比他深的splay点中找到最大的mx1+1+ch[0]->size再更新一边才行。