Lynkcat的博客

博客

PKUSC 2024 简单写写

2024-05-15 23:30:03 By Lynkcat

回文路径

枚举回文中心在哪一行的哪个位置,那么在这一行的回文串一定是取的越长越好,可以直接二分哈希。

正方形计数

枚举一条 (x,y) 向量表示第二个点与第一个点之间的位移,满足 x+y>0,计算包含这个向量的合法正方形的个数。

把其他三个点相对于第一个点的位移都求出来,关于 n 个半平面可以得到新的 n 个半平面。

求出半平面交之后,可以得到若干 ax+by+c0 的限制,使用一些差分的手段后可以转化成求一个 [0,MAX]×[0,MAX] 的矩形与一个半平面的交形成一个三角形,求这个三角形中的整点个数,由于斜率只有 n 种,进行 n 遍前缀和即可。

独立

树上最大权独立集的经典做法是设 dpk,0/1 表示 k 这个位置是否被选中,不难发现有 max(dpk,0,dpk,1)dpk,0V

考虑设 sizk 表示 k 子树的大小,设 fk,i 表示 k 子树内,max(dpk,0,dpk,1)dpk,0=i 的方案数。那么有答案为 kifk,i×i×mnsizk

可以证明 fk,i 在当 i0 的时候是关于 i 的一个 siz 次多项式,因此考虑拉格朗日插值。

考虑 u 转移到 k 的时候是个减法卷积,因此我们试图求出 fk,msizk...m,这可以直接减法卷积。这部分复杂度是 sizklogsizk 的。

接着我们直接使用 fk,msizk...m 点值平移出 fk,1...sizk。这样就能够继续转移到 k 的父亲了。求答案就用 fk,i×i×mnsizk 的前缀和插一下就行了。同样的 fk,0 的处理也可以拉插,当 u 转移到 k 时(fkfufk),把 {fk,i×(j=ifu,j)} 弄几个能算的出来拉插就能转移到新的 fk,0 了,当然还要加上 fk,0 的贡献,不过处理方式是一样的。

因此整个题可以做到 O(n2logn) 的时间复杂度。

分流器

二分答案 ans,设 fi 表示 i 被访问到的次数,那么接下来一定两条出边会各被访问一半,也就是 fouti,0+=fi2fouti,1+=fi2。在过程中判一下是否满足每个点是奇数即可,用 ull 压位高精时间复杂度 O(n3w)

注意到 ans 只有 lowbit 有用,所以答案一定是 2 的某个次幂,二分指数即可做到时间复杂度 O(n2lognw),可以通过。

upd:也可以不需要二分,直接求 ans2n 的时候每个点的 lowbit 的最小值即可。

排队

扫描线,每个询问在左端点处插入,右端点处查询。

因为询问初始给的初值均为 0,因此先插入的询问在同一个右端点处的答案不会比后插入的要小。

因此,将询问按左端点排序,每次的操作形如找到一个区间满足区间内的值都在 [l,r] 内,然后集体 +1,可以在树状数组上二分实现。

时间复杂度 O(nlogn)

最短路径

Comments

[+18]
Kevin5307 请写题解
  • 2024-05-16 17:24:52
  • Reply
Comment replies
Kevin090228🍬:https://qoj.ac/blog/kevin5307/blog/864
[+14]
PKUSC 2024 简单写写
  • 2024-05-16 18:13:46
  • Reply
Comment replies
[+12]
D1T3 怎么证明是多项式,m = 1000 ,n = 2 这个结论是不是就有问题了/yiw/yiw
  • 2024-05-16 22:50:13
  • Reply
Comment replies
Lynkcat:哪里有问题
Lynkcat:你可以直接考虑减法卷积的过程,可以直接写成多项式的样子吧
d2t1不是n2/w吗
  • 2024-05-17 15:37:18
  • Reply
[+4]
d2t1 二分分母是不是完全没必要
  • 2024-05-17 19:54:08
  • Reply
Comment replies
Milmon:是的,我是 n^2/w
[+2]
Lynkcat 为啥这题最优解没开高精度,unsigned short 过了??? 这个能卡么
  • 2024-05-21 10:00:29
  • Reply
Comment replies
Lynkcat:你说的是 d2t1吗,我觉得应该能卡的?
Acoipp:只需要 i-->i+1,i-->n+1 就卡掉了
Lynkcat:Reply Acoipp:并不行
Milmon:Reply Lynkcat: 疑似可以卡 #include<bits/stdc++.h> using namespace std; int main(){ printf("%d\n",500); for(int i=1;i<=200;i++) printf("%d %d\n",i+1,201); for(int i=201;i<=500;i++) printf("%d %d\n",i+1,501); for(int i=1;i<=500;i++) printf("0%c"," \n"[i==500]); return 0; }
Milmon:n 开大就是这样 #include<bits/stdc++.h> using namespace std; int main(){ printf("%d\n",50000); for(int i=1;i<=20000;i++) printf("%d %d\n",i+1,20001); for(int i=20001;i<=50000;i++) printf("%d %d\n",i+1,50001); for(int i=1;i<=50000;i++) printf("0%c"," \n"[i==50000]); return 0; }
Acoipp:Reply Lynkcat:事实上我们造数据的时候就卡掉了它,顺带还卡掉了一份高精度写错了的提交 数据就是 i-->i+1,i-->n+1,n=5e4,这个时候答案是 2^n
Milmon:Reply Acoipp: 不是啊,他AC了而且你这个构造确实卡不掉他,你看一下他的实现就知道了
Acoipp:Reply Milmon:啊?wc 我唐了
Lynkcat:Reply Acoipp:啊,所以你参与了这题的出题工作吗
Acoipp:Reply Lynkcat:没有,只是赛后给某 OJ (不是 QOJ)造了数据

Post a comment

You can use @mike to mention the user mike.

If you wish to input the '@' character, please use @@