• [ARC125D] Unique Subsequence


    前言

    有网赛 DEBUFF 加身的我果然不一样,直接梦中想题。

    题目

    AtCoder

    题目大意:

    给一个长度为 (N) 的序列 (A)(s)(A) 的非空子序列,询问有多少不同的个 (s) 可以被 (A) 唯一表示,答案对 (998244353) 取模。

    • (1le Nle 2 imes 10^5)
    • (1le A_ile N)
    • 所有数都是整数。

    注:(s)(A) 唯一表示的意思是,只存在一个独一无二的序列 (id) 使得 (A_{id(i)}=s_i).

    其实英文题面挺短的,可以看一看。

    讲解

    为方便表示,我们令 (A_0=id_0=0,A_{N+1}=id_{N+1}=N+1).

    我们将唯一表示的条件具体化,可以发现对于 (iin[0,N])(A_{id(i)+1},A_{id(i)+2},...,A_{id(i+1)-1}) 不等于 (A_{id(i)})(A_{id(i+1)})

    也就是说我们选的子序列中的相邻两个数中间不能有和它们相同的数。

    然后我们就可以考虑对以权值 (i) 结尾的方案数进行维护。

    单点修改,区间查询,用树状数组即可。

    代码

    一看就懂的代码
    //12252024832524
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define TT template<typename T>
    using namespace std; 
     
    typedef long long LL;
    const int MAXN = 200005;
    const int MOD = 998244353;
    int n,ans;
    int lst[MAXN],dp[MAXN];
     
    LL Read()
    {
    	LL x = 0,f = 1;char c = getchar();
    	while(c > '9' || c < '0'){if(c == '-')f = -1;c = getchar();}
    	while(c >= '0' && c <= '9'){x = (x*10) + (c^48);c = getchar();}
    	return x * f;
    }
    TT void Put1(T x)
    {
    	if(x > 9) Put1(x/10);
    	putchar(x%10^48);
    }
    TT void Put(T x,char c = -1)
    {
    	if(x < 0) putchar('-'),x = -x;
    	Put1(x); if(c >= 0) putchar(c);
    }
    TT T Max(T x,T y){return x > y ? x : y;}
    TT T Min(T x,T y){return x < y ? x : y;}
    TT T Abs(T x){return x < 0 ? -x : x;}
     
    int B[MAXN];
    int lowbit(int x){return x & -x;}
    void Mod(int &x,int val){x += val;if(x >= MOD) x -= MOD;}
    void Add(int x,int val){for(;x <= n;x += lowbit(x)) Mod(B[x],val);}
    int Sum(int x){int ret = 0;for(;x >= 1;x -= lowbit(x)) Mod(ret,B[x]);return ret;}
     
    int main()
    {
    //	freopen(".in","r",stdin);
    //	freopen(".out","w",stdout);
    	n = Read();
    	for(int i = n,val;i >= 1;-- i)//倒着来是为了计数方便
    	{
    		val = Read();
    		if(lst[val]) dp[i] = Sum(lst[val]),Add(lst[val],MOD-dp[lst[val]]);
    		else dp[i] = Sum(n)+1;
    		Add(lst[val] = i,dp[i]);
    	}
    	for(int i = 1;i <= n;++ i) Mod(ans,dp[lst[i]]);
    	Put(ans);
    	return 0;
    }
    
  • 相关阅读:
    移植OpenSSH到arm手记
    编译内核模块找不到内核头文件解决办法
    多线程编程
    多线程编程
    MFC中如何清空CListBox
    Windows文件自删除的两种方法
    【转】显示一个打开文件夹的对话框,并得到用户选择的目录:
    【转】UpdateData()函数
    Windows命名规则
    CListControl如何删除所有子项
  • 原文地址:https://www.cnblogs.com/PPLPPL/p/15176196.html
Copyright © 2020-2023  润新知