【考试总结2021-02-25】结束

要换换名字

考虑如果一个串有大于 (n) 个子序列,那么一定不用考虑,所以找到每个串的前 (n+1) 个子序列

显然在串比较长的情况下子序列长度不会太大,用 (map) 存标号就行了

找子序列的部分使用子序列自动机,注意空间第一维要开长度大小

剩下的显然是二分图匹配,写一个网络流,一开始源点向子序列的边不带流量

最后枚举答案 (ans),对于长度为 (ans) 的子串维护即可

动态半平面交

真正的厉害题,但是真的不清楚为啥 (skyh) 说这个有手就行

前置

  • 区间 (lcm)

对于每个质因子的次幂数维护一个单调栈,套上一个扫描线或者可持久化就行了

  • ( exttt{dsu on tree})

先树剖一下,然后对于每个枚举的点,先计算轻子树答案,清空贡献

再计算重子树答案,不清空贡献,计算当前节点答案,最后扫一次轻子树贡献


回到本题,可持久化一个线段树,树上的深度存对应点答案的贡献

(深度对应贡献的做法是我没想到的)

对树进行 ( exttt{dsu on tree}) 来预处理贡献

写的时候是很艰难的,但是最后还是弄明白写出来了

inline void calc2(int x, int anc) {
    for (auto p : div[x]) {
        int num = id[p.first];
        auto it = s[num].lower_bound(make_pair(dep[x], 0)), tp = it;

        if (it != s[num].begin()) {
            tp = it;    //在深度小于之的有比它次数更大的
            --tp;

            if (tp->second >= p.second)
                continue;
        } else if (it != s[num].end() && it->first == dep[x] && it->second >= p.second)
            continue;//深度相同有次数更大的

        int lst;

        if (it == s[num].begin())
            lst = 0;
        else {
            tp = it;    //维护差分
            --tp;
            lst = tp->second;
        }

        while (1) { //单调栈弹栈
            it = s[num].lower_bound(make_pair(dep[x], 0));

            if (it == s[num].end())
                break;

            upd(rt[anc], 1, mx, it->first, 
            ksm(p.first,(it->second - lst) * (mod - 2) % (mod - 1))); //把单调栈后面的部分的都先去掉

            if (it->second > p.second)
                break;

            lst = it->second;
            s[num].erase(it);
        }

        it = s[num].lower_bound(make_pair(dep[x], 0));

        if (it == s[num].begin())
            lst = 0;
        else {
            tp = it;    //差分:当前差前面
            --tp;
            lst = tp->second;
        }

        upd(rt[anc], 1, mx, dep[x], ksm(p.first, p.second - lst)); //更新答案

        if (it != s[num].end())
            upd(rt[anc], 1, mx, it->first, ksm(p.first, it->second - p.second)); //后面差当前

        s[num].insert(make_pair(dep[x], p.second)); //加入当前维护的集合
    }

    for (reg int i = head[x]; i; i = e[i].nxt)
        if (e[i].to != fa[x])
            calc2(e[i].to, anc); //不需要判重儿子
}//dsu on tree 把轻子树的贡献统计

获取名额

题面转化一下就是 (ans=1-prod 1-frac{a_i}x)

直接搞前缀积显然精度是不够的,那么考虑如何分治求区间询问

这个显然是个付公主的背包,也就是

[ans=1-e^{sum ln(1-frac{a_i}x)} ]

(exp) 函数是能用的,用 (st) 表进行最值分治,如果当前区间最值 (ge x imes 0.4) 分治两边

如果不是那么维护展开后的前 (30)

卡精度的一个地方是要先除掉 (max) 否则展开幂大了之后就爆精度了

原文地址:https://www.cnblogs.com/yspm/p/14454682.html