首页 > 其他分享 >[AGC054C] Roughly Sorted 题解

[AGC054C] Roughly Sorted 题解

时间:2023-12-19 12:34:14浏览次数:27  
标签:int 题解 位置 个数 AGC054C MAXN Sorted 序列 操作

题意

定义一种操作为交换 \(a_{i}\) 和 \(a_{i-1}\)。对于一个长度为 \(n\) 的排列,你需要操作若干次,使这个序列变合法,一个序列合法指:满足对于每一个 \(1\le i \le n\),都满足包含 \(a_i\) 的逆序对的个数不超过 \(k\),并且要求最小化操作次数。现在给定一个操作后的序列,询问原序列可能的个数。答案对 \(998244353\) 取模。

思路

我们先来思考如何求从一个序列变为合法序列的最小操作次数。因为操作只能交换相邻两个数,所以一次操作最多只能使逆序对的个数减一。设 \(b_{i}\) 表示包含第 \(i\) 个数的逆序对个数。那么我们每一次都尽量贪心地操作,即操作的 \(i\) 都满足:\(b_{i}>k\) 并且 \(a_{i}<a_{i-1}\)。因为这样操作才能有效果,并且效果最大。

那我们就可以猜想是不是每一次都可以这样操作?那就需要考虑是不是每一次都能找到一个位置满足上述条件。答案是肯定的。考虑用反证法来证明,如果没有位置满足上述条件,即对于每一个 \(b_{i}>k\),都有 \(a_{i-1}< a_{i}\)。那么又因为 \(a_{i-1}< a_{i}\),所以 \(b_{i}\ge b_{i-1}>k\),所以又可以推出 \(a_{i-2} < a_{i-1}< a_{i}\),以此类推,最终可以得到:

\(\begin{cases}a_{1} <a_2<\dots <a_i \\b_i \ge b_i-1 \ge \dots \ge b_1 \end{cases}\)

所以 \(k=0\),但是题目上说 \(k \ge 1\),所以矛盾,于是得证。所以证明到了每一次一定能按照最优的方案去操作,总结操作方式为:每次选择一个 \(i\) 满足 \(b_{i}>k\) 并且 \(a_{i}<a_{i-1}\),交换 \(a_i\) 和 \(a_{i-1}\)。

回到原题,再来考虑如何用最终的序列算出原序列可能的个数。首先,我们只考虑 \(b_{i}=k\) 的位置,因为如果 \(b_{i} \ne k\),那么这个数现在的位置和原来的位置是没有变化的。考虑 \(b_i=k\) 的位置,我们会发现原序列中 \(a_{i}\) 这个数的位置一定在 \(i\) 后面,并且在 \(i\) 后面的任意一个位置都可以选择。因为如果在 \(i\) 的前面的话,显然它不会向后移动。所以最终的答案是 \(\prod_{b_{i}=k}^{} (n-i+1)\),总时间复杂度 \(O(n^{2})\),用树状数组可以优化到 \(O(n \log n)\)。

Code

#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
const int MAXN = 5e3 + 10;
const int mod = 998244353;
int n,k,a[MAXN],b[MAXN],id[MAXN],p,ans;
signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
	cin >> n >> k;
	for(int i = 1;i <= n;i++) cin >> a[i];
	for(int i = 1;i <= n;i++)
	{
		int sum = 0;
		for(int j = 1;j < i;j++) if(a[j] > a[i]) sum++;
		if(sum == k) id[++p] = i; 
	} 
	ans = 1;
	for(int i = 1;i <= p;i++) ans = (ans * (n - id[i] + 1)) % mod;
	cout << ans; 
	return 0;
}

标签:int,题解,位置,个数,AGC054C,MAXN,Sorted,序列,操作
From: https://www.cnblogs.com/Creeperl/p/17913455.html

相关文章

  • P2391 白雪皑皑 题解
    原题链接:P2391。并查集好题。首先我们知道,并查集在一个无向图中可以维护两点之间的连通性,判断条件为:\(find(u)==find(v)\)。而对于这道题来说,我们可以用并查集来维护一个序列区间的重叠性或者说区间的连通性。因为题目上说了后面的操作会覆盖前面的操作,所以我们可以考虑倒序进行......
  • [ABC239Ex] Dice Product 2 题解
    原题链接:ABC239Ex。题意不多赘述。看到求期望值,我们想到可以用期望DP。设\(dp_{i}\)表示最终结果大于等于\(i\)时的操作次数的期望值。那么我们可以得到一个基本的状态转移方程:\(dp_{i}=\frac{1}{n}\times\sum_{j=1}^{n}dp_{\left\lceil\frac{i}{j}\right\rceil}+......
  • Prefix Purchase 题解
    题意给定一个长度为\(n\)的序列\(ans\),初始值全部为\(0\)。你一共有\(k\)个硬币,你可以选择花\(a_{i}\)个硬币来使\(ans_{1}\)到\(ans_{i}\)中的所有数加一。求最终能得到的\(ans\)序列中字典序最大的一个。思路首先我们可以发现一个很显然的性质:如果满足\(a_{i}......
  • Sum of XOR Functions 题解
    题意给定一个数\(n\)和一个包含\(n\)个数的序列\(a\),求出以下式子模\(998244353\)的值:\(\sum_{i=1}^{n}\sum_{j=i}^{n}f(i,j)\times(j-i+1)\)。其中\(f(i,j)\)的值为\(a_{i}\oplusa_{i+1}\oplusa_{i+2}\oplus...\oplusa_{j}\)。思路首先我们可以考虑这道题的......
  • Candy Party (Hard Version) 题解
    原题链接:CF1868B2,简单版:CF1868B1。题意有\(n\)个人,第\(i\)个人手上最初有\(a_{i}\)颗糖。现在每个人可以把自己手中的糖选一些给不多于一个人,同时每个人也只能接受不多于一个人的糖,选出的糖的数量必须是二的次幂。问能否能让每个人最终手上的糖的数量相等。思路首先,这......
  • 【0909 B组】切蛋糕 题解
    原题链接:切蛋糕。题意给定一个\(n\)行\(m\)列的蛋糕,问横着切\(i\)刀,竖着切\(j\)刀后美味度最小的蛋糕的美味度尽可能大。一块蛋糕的美味度为它所含有的小块的美味度之和。数据范围:\(1\len,m\le14\)。思路看到数据范围,我们可以考虑一种类似于状态压缩的思想,先枚举......
  • Cyclic Operations 题解
    前言看这道题有好多巨佬都是用Tarjan来做的,在这里讲一个自认为比较简单的做法,(不到\(30\)行)。题意题意比较难讲,建议自己去看一下翻译,在这里不多赘述。思路首先看到题目中间给的一个每一次操作的式子:\(a_{l_{i}}=l_{(i\modk)+1}\)。仔细观察这个式子后会发现,其实每一次......
  • P4630 [APIO2018] 铁人两项 题解
    今天学习了圆方树,并且做了一道和这道题很像的题,于是就又来做了一下这道题。题意给定一张不保证连通的无向图。求有多少个点对\((a,b,c)\)满足\(a\)到\(c\)的简单路径上经过了点\(b\)。思路显然圆方树。点双缩点过后构造一颗圆方树,然后考虑如何计算答案。圆方树有一个实......
  • [ABC315G] Ai + Bj + Ck = X (1 <= i, j, k <= N) 题解
    原题链接:ABC315G前置知识:扩展欧几里得算法。如果还不会扩欧的话,建议先去做这道题。题意给定\(n,a,b,c,k\)。求有多少个\(x,y,z(x,y,z\len)\)满足\(ax+by+cz=k\)。思路首先看到题目给出的方程式:\(ax+by+cz=k\)。我们会发现很像扩欧板子中的:\(ax+by=k\)。只不过又多了一......
  • [ABC318G] Typical Path Problem 题解
    原题链接:ABC318G显然是圆方树。点双缩点过后建立一颗以点\(c\)为根节点的圆方树,考虑什么情况是合法的。从点\(a\)开始往上跳直到跳到点\(c\),如果中间走过了某一个方点并且这个方点与\(b\)点有直接连边,那么就是合法的;否则不合法。证明:如果路径中所经过的方点和\(b\)点......