zoukankan      html  css  js  c++  java
  • JOI汉堡肉

    不靠谱做法:随机化。

    靠谱做法:观察发现当k<4时,答案一定处于一个关键矩形(min(r[i]),max(l[i]),min(y[i]),max(x[i]))的边界。

    如果不处在边界上,显然可以把它移到边界。

    当k<4时,由抽屉原理可得一定有一个关键点在某个定点。

    搜索所有顶点,在搜索中可以删除这个点,移除所有包含它的矩形再做一遍算法。

    这个算法在k<4是正确的。但是在k=4时,可能所有点都在边上,显然上面的算法错误。

    问题被我们转化成了求一个让所有点都在边上的一组解。使用4个变量描述边被选择的位置。

    考虑每个矩形,问题实际上可以被分成几类讨论:

    1.矩形完全包含关键矩形,不作处理

    2.矩形与关键矩形不交于边界,无解(题目不会无解)

    3.矩形与关键矩形交于一角,则问题转化为两个不等式有至少1个要成立。

    4.矩形与关键矩形交于一边,则问题转化成要求一个不等式成立。

    5.矩形覆盖了关键矩形的一边,则这一边一定有一个点在这个矩形中,所以不作处理

    实际上,可以使用2sat解决这个问题。

    设f[x][i]表示x是否<=i,则~f[x][i]=x是否>i

    所以,l<=x<=r实际上就是让f[x][l-1]为false,f[x][r]为true,就是让2个变量为true则4情况可以被处理。

    3情况的处理可以把不等式转化一下。

    l<=a<=r且x<=b<=y就是(~f[a][l-1]&f[a][r])|(~f[b][x-1]&f[b][y])

    这个不是2sat形式,但是可以使用or的分配律转化成(~f[a][l-1]|~f[b][x-1])&(~f[a][l-1]|f[b][y])&(f[a][r]|~f[b][x-1])&(f[a][r]|f[b][y])

    变成了4个公式,内部的形式形如(x|y),用and运算符连接,这样子就变成了2sat形式。

    把所有f[x][l]->f[x][l+1]连边,则跑一下2sat,用tarjan的dfs序输出方案即可

    注意要离散化。这道题中如果直接跑2sat,则时间复杂度高达$O(10^9)$。

    实际上,这道题可以把r和l-1这些关键点存下来,关键点到下一个关键点的一段的值肯定是相同的。所以可以把连续相同的点缩在一起,时间复杂度降到O(nlogn)

    总时间复杂度$O(nlogn+n*4^k)$

  • 相关阅读:
    CF258D
    CF662C
    CF1295F
    CF1406E
    CF1270F
    CF1278F
    CF1523E
    CF1554E
    算法第四章上机实践报告
    LCA RMQ+ST表学习笔记
  • 原文地址:https://www.cnblogs.com/cszmc2004/p/12820792.html
Copyright © 2011-2022 走看看