首页 > 其他分享 >[AGC061C] First Come First Serve 题解

[AGC061C] First Come First Serve 题解

时间:2023-08-18 16:26:20浏览次数:40  
标签:right 题解 valueType Serve T1 MOD left First mod

题意

有两个长度为 \(n\) 的正整数列 \(A,B\)。表示数 \(i\) 可以填到 \(A_i\) 或 \(B_i\) 两个位置中的一个。问删去空位之后可以形成的排列种数。

(\(1 \le n \le 5 \times 10^5\),\(A_i,B_i\) 取遍 \(\left[1, 2n\right]\))。

题解

首先可以发现填数的方案数为 \(2^n\),发现会计算进重复情况,考虑什么时候会有重复情况,如果 \(\forall i \neq x, \left[A_i, B_i\right] \cap \left[A_x, B_x\right] = \varnothing\) 或是 \(\exists j \neq i,A_i < A_j \land B_i < B_j\) 均会产生重复情况。换句话说就是有一些数选择 \(A_i\) 和 \(B_i\) 对最终形成的排列没有影响,却被计算了多次。

设一个序列 \(C_i\),满足 \(C_i = 0 \Rightarrow\) 数字 \(i\) 填在位置 \(A_i\), \(C_i = 1 \Rightarrow\) 数字 \(i\) 填在位置 \(B_i\)。考虑一个数什么时候会有重复情况,如果数字 \(i\) 选择了填在 \(B_i\) 但是没有其他数字填在 \(\left(A_i, B_i\right)\),那么这个数字就会产生重复情况,记这种状态为 \(i\) 不合法,考虑从所有状态中容斥掉不合法状态。

记 \(L_i = \max\limits_{j = 1}^{n} B_j > A_i,R_i = \min\limits_{j = 1}^{n} A_j < B_i\),那么如果 \(i\) 不合法,可以推出 \(\forall j \in \left[L_i, i\right] C_j = 0 \land \forall j \in \left(i, R_i\right] C_j = 1\),换句话说就是区间 \(\left[L_i,R_i\right]\) 的选择情况会被确定下来。再发现一点性质,如果存在 \(i < j\),使得 \(R_i \ge L_j\),那么 \(i, j\) 一定同时合法,也就是说,最终需要容斥的局面中的区间集一定两两不交。

考虑容斥,设当前的状态集合 \(S\) 为形如 \(\left\{\left(L_i, R_i\right)\right\}\) 的区间集,那么最终的答案为

\[2^n - \sum\limits_{S} (-1)^{\lvert S \rvert - 1} 2^{\operatorname{len}(S)} \]

其中 \(\operatorname{len}(S) = \sum\limits_{\left(l, r\right) \in S} r - l + 1\),即集合内所有区间的长度之和。

考虑进行容斥 DP,设 \(f_i\) 为考虑了完全包含于 \(\left[1, i\right]\) 的区间组成的状态后的方案数。边界为 \(f_0 = 2^n\),因为没有考虑任何一个状态。考虑将所有区间按右端点存储,转移时枚举右端点为 \(i\) 的所有区间的左端点,并计算当前区间的贡献即可。转移式如下

\[f_i = \sum\limits_{R_x = i}\sum\limits_{j = 0}^{L_x - 1} -2^{-(R_x - L_x + 1)}f_j \]

使用前缀和优化即可以 \(\mathcal{O}(n)\) 的复杂度通过本题。

Code

#include <bits/stdc++.h>

typedef long long valueType;
typedef std::vector<valueType> ValueVector;
typedef std::vector<ValueVector> ValueMatrix;

constexpr valueType MOD = 998244353;

template<typename T1, typename T2, typename T3 = valueType>
void Inc(T1 &a, T2 b, const T3 &mod = MOD) {
    a = a + b;

    if (a >= mod)
        a -= mod;
}

template<typename T1, typename T2, typename T3 = valueType>
void Dec(T1 &a, T2 b, const T3 &mod = MOD) {
    a = a - b;

    if (a < 0)
        a += mod;
}

template<typename T1, typename T2, typename T3 = valueType>
T1 mul(T1 a, T2 b, const T3 &mod = MOD) {
    return (long long) a * b % MOD;
}

template<typename T1, typename T2, typename T3 = valueType>
void Mul(T1 &a, T2 b, const T3 &mod = MOD) {
    a = (long long) a * b % mod;
}

template<typename T1, typename T2, typename T3 = valueType>
T1 pow(T1 a, T2 b, const T3 &mod = MOD) {
    T1 result = 1;

    while (b > 0) {
        if (b & 1)
            Mul(result, a, mod);

        Mul(a, a, mod);
        b = b >> 1;
    }

    return result;
}

class Inverse {
public:
    typedef ValueVector container;

private:
    valueType size;
    container data;
public:
    explicit Inverse(valueType n) : size(n), data(size + 1, 0) {
        data[1] = 1;

        for (valueType i = 2; i <= size; ++i)
            data[i] = mul((MOD - MOD / i), data[MOD % i]);
    }

    valueType operator()(valueType n) const {
        return data[n];
    }
};

int main() {
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout.tie(nullptr);

    valueType N;

    std::cin >> N;

    ValueVector A(N + 1), B(N + 1), L(N + 1), R(N + 1);

    for (valueType i = 1; i <= N; ++i)
        std::cin >> A[i] >> B[i];

    valueType pointer = 0;
    for (valueType i = 1; i <= N; ++i) {
        while (pointer < N && B[pointer + 1] < A[i])
            ++pointer;

        L[i] = pointer + 1;
    }

    pointer = N + 1;
    for (valueType i = N; i >= 1; --i) {
        while (pointer > 1 && A[pointer - 1] > B[i])
            --pointer;

        R[i] = pointer - 1;
    }

    ValueMatrix left(N + 1);
    for (valueType i = 1; i <= N; ++i)
        left[R[i]].emplace_back(L[i]);

    ValueVector F(N + 1, 0);

    F[0] = pow(2, N);
    Inverse Inv(2);

    for (valueType i = 1; i <= N; ++i) {
        Inc(F[i], F[i - 1]);

        for (auto const &iter: left[i])
            Dec(F[i], mul(pow(Inv(2), i - iter + 1), F[iter - 1]));
    }

    std::cout << F[N] << std::endl;

    return 0;
}

标签:right,题解,valueType,Serve,T1,MOD,left,First,mod
From: https://www.cnblogs.com/User-Unauthorized/p/solution-AT-AGC061-C.html

相关文章

  • 题解:【CF858E】 Tests Renumeration
    题目链接一点模拟下下火。首先一定不能覆盖的,只能一点一点挪。将已经在合法位置上的去掉,剩下的测试分为四类:不碍事的样例测试。不碍事的常规测试。占据了样例测试位置的常规测试。占据了常规测试位置的样例测试。将\(1\simn\)中还未使用的空闲位置记录下来,结论是只需......
  • Maui Blazor 安卓文字随系统文字缩放问题解决
    MauiBlazor的文字在正常情况下会随着用户手机内的系统文字设置大小而变化,所以可能导致手机应用内APP的布局由于文字变得过大或者过小而错乱。可以通过设置Webview里的文字缩放,保持应用内文字大小不变,代码如下:1.首先在Mainpage.xaml里设置好初始化事件,BlazorWebViewInitialize......
  • 无涯教程-Perl - ucfirst函数
    描述该函数返回的EXPR值仅将第一个字符大写。如果省略EXPR,则使用$_。语法以下是此函数的简单语法-ucfirstEXPRucfirst返回值此函数返回第一个字符为大写的String。例以下是显示其基本用法的示例代码-#!/usr/bin/perl-w$string='thecatsatonthemat.';$u_......
  • [AGC003F] Fraction of Fractal 题解
    一道很好的矩阵题,可以尝试作为矩阵转移的优质练习题。思路考虑由于黑点在原图中处于联通的状态。分三种情况讨论。上下左右联通。考虑这种情况下,不断分形后。最终产生的依然是一整个的大连通块。故,答案为一。上下左右都不连通。那么每一次分形后就会产生黑色点个连通......
  • 2023年 8月15日普及组南外集训题解
    A查找最大元素扫一遍确定最大值,如果是最大值输出字符和"(max)",不是的话只输出字符#include<iostream>#include<cstring>usingnamespacestd;charmaxx;strings;intmain(){cin>>s;for(inti=0;i<s.size();i++)if(s[i]>=maxx)......
  • Atcoder_[abc284E]Count Simple Paths题解
    题目链接这题就是很简单的图上深搜,我觉得放在E题太水了,代码里有详细注释。#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongvector<int>v[200010];//邻接表intans;//答案boolvis[200010];//vis[i]记录i号点有没有被访问过voiddfs(intx)......
  • ARC145C 题解
    problem&blog。小清新结论题。提供一个不需要脑子就可以AC的方法:看样例解释,猜到一定是\((1,2)(3,4)\)这样子,于是暴力,把前几项输进OEIS里,做完了。显然取\(\forall|A_i-B_i|=1\)最优。证明:对于\(x-3,x-2,x-1,x\),配对:\((x-3,x-2)(x-1,x)\)的贡献为\((x-3)(x-2)+......
  • 国产麒麟系统KylinOS Server V10 SP2安装MySQL 8.0.26—源码编译安装
    一:操作系统环境检查1.1首先确认操作系统版本是KylinOSServerV10SP2麒麟操作系统KylinosServerV10SP2使用的安装介质是Kylin-Server-10-SP2-x86-Release-Build09-20210524.iso,执行以下命令查看版本:cat/etc/kylin-releasecat/proc/version 1.2检查系统是否......
  • json-server安装
    一、下载安装:【json-server网址】https://www.npmjs.com/package/json-server#使用npm全局安装json-server:npminstall-gjson-server#可以通过查看版本号,来测试是否安装成功:json-server-v二、启动db.json数据及相关参数:json-server--watch.\db.json--port5000......
  • vue3项目,vie框架,相对路径图片,测试时正常显示,发布后不显示问题解决方案
    参考Vite官网的说明,修改图片的引用路径后,图片发布后可以正常显示constimgUrl=newURL('./img.png',import.meta.url).hrefdocument.getElementById('hero-img').src=imgUrl官网地址: https://cn.vitejs.dev/guide/assets.html ......