首页 > 其他分享 >题解 AGC058B 【Adjacent Chmax】

题解 AGC058B 【Adjacent Chmax】

时间:2023-09-19 14:25:50浏览次数:34  
标签:5010 node int 题解 leq Adjacent 区间 Chmax id

posted on 2022-08-15 00:08:56 | under 题解 | source

problem

一个长为 \(n\) 的排列 \(P\),每次可以选择一个 \(i\),令 \(v=\max(P_i,P_{i+1})\),使 \(P_i=P_{i+1}=v\),求若干次操作后有多少种不同的序列。\(1\leq n\leq 5000\)。

solution

显然地,对于一个 \(P_i\),它要么被完全覆盖,要么会占领一段区间 \([l_i,r_i]\)。显然这些 \([l_i,r_i]\) 要连续,它占领的这一段区间是由这个最大值扩散出去的,所以不能扩散到比它大的值。令它能扩散的区域是 \([L_i,R_i]\)(这部分暴力),显然 \(L_i\leq l_i\leq r_i\leq R_i\)(这里注意 \(i\) 号点最终不一定会被它自己覆盖)。于是 DP,设 \(f_{i,j}\) 表示当 \(r_i=j\) 时的方案数,枚举 \(l_i\) 在哪里,从 \(f_{i-1,l_i-1}\) 转移就可以了。

code

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int P=998244353;
int n,a[5010];
LL f[5010][5010];
int main(){
//	#ifdef LOCAL
//	 	freopen("input.in","r",stdin);
//	#endif
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	a[0]=a[n+1]=1e9;
	f[0][0]=1;
	for(int i=1;i<=n;i++){
		int l=i,r=i;
		while(l>=1&&a[l-1]<=a[i]) l--;
		while(r<=n&&a[r+1]<=a[i]) r++;
		memcpy(f[i],f[i-1],sizeof f[i]);
		LL sum=f[i][l-1]; 
		for(int j=l;j<=r;j++){
			f[i][j]=(f[i][j]+sum)%P;
			sum=(sum+f[i-1][j])%P;
		}
	}
	printf("%lld\n",f[n][n]);
	return 0;
}

一些关于这个题的思考

考场上得出了 \(L_i\leq l_i\leq r_i\leq R_i\) 的结论,然后往区间 DP 上面想了,最后不想写代码了。

在手推的时候,我发现了一些性质:

  • 对于任意 \([L_i,R_i]\),它们要么完全包含,要么没有交集。
  • 所有 \([L_i,R_i]\) 可以构成一棵有包含关系的树。\(P_i<P_{fa_i}\)。
  • 对于树上一个区间,它的子节点加上这个区间原来在的编号,刚好完全覆盖这个区间。

于是,做法是,在这棵树上 dfs,算出这个区间的前后缀 DP 值,滚动更新一下。但是没写出来,可能是假的。但是这个树是有价值的。

struct node{
	int x,id,l,r;
	node(int x=0,int id=0,int l=0,int r=0):x(x),id(id),l(l),r(r){}
	bool operator<(node b){return x>b.x;}
};
bool cmp(node a,node b){return a.l<b.l;}
int n;
node a[5010];
vector<node> g[5010];
int get(int i,int d){
	for(int j=i;0<=j&&j<=n+1;j+=d){
		if(a[j].x>a[i].x) return j-d;
	}
	return -114514;
}
int main(){
//	#ifdef LOCAL
//	 	freopen("input.in","r",stdin);
//	#endif
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i].x),a[i].id=i;
	a[0].x=a[n+1].x=1e9;
	for(int i=1;i<=n;i++) a[i].l=get(i,-1),a[i].r=get(i,1);
	sort(a+1,a+n+1);
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			if(a[j].l<=a[i].l&&a[i].r<=a[j].r){
				g[j].push_back(a[i]);
				break;
			}
		}
	}
	for(int i=1;i<=n;i++) sort(g[i].begin(),g[i].end(),cmp);
	printf("%lld\n",dfs(1).f.back());
	return 0;
}

标签:5010,node,int,题解,leq,Adjacent,区间,Chmax,id
From: https://www.cnblogs.com/caijianhong/p/solution-AGC058B.html

相关文章

  • AT_arc165_d 题解
    AT_arc165_d[ARC165D]SubstringComparison题解Links洛谷AtCoderDescription给定正整数\(n,m\)和\(m\)个形如\((A_{i},B_{i},C_{i},D_{i})\)的限制条件。判断是否存在一个长度为\(n\)的序列\(P\)满足\(\foralli\in[1,m]\),\(P_{A_{i}\dotsB_{i}}\)字典序......
  • AT_arc165_b 题解
    AT_arc165_b[ARC165B]SlidingWindowSort2题解Links洛谷AtCoderDescription给定正整数\(n,k\)和一个长度为\(n\)的整数\(P\),你需要选择一个长度为\(k\)的区间\([l,l+k-1]\),将这个区间从小到大排序。找到操作后最终字典序最大的排列。\(1\leqk\leqn\l......
  • 【Android】折叠效果CoordinatorLayout+AppBarLayout首页效果&& CoordinatorLayout抖
    亲测效果如下:布局结构<?xmlversion="1.0"encoding="utf-8"?><android.support.constraint.ConstraintLayoutxmlns:android="http://schemas.android.com/apk/res/android"xmlns:app="http://schemas.android.com/apk/res-auto&qu......
  • Azamon Web Services 题解
    AzamonWebServices看到目前题解都是\(O(n^2)\)的复杂度,来一发\(O(nlogn)\)的贪心题解。思路很简单,先求经过至多一次的交换后,最小的字符串\(S\)。再和\(T\)比较,如果小于就输出,否则无解。问题转化成了两个子问题:求经过至多一次的交换后,最小的字符串\(S\)。和\(T\)......
  • CF762C Two strings 题解
    洛谷传送门CF传送门题意给你两个字符串\(a\)和\(b\),你可以在\(b\)中删去尽量短的子段,使得\(b\)是\(a\)的子序列。求出最后的\(b\)。思路真是奇了怪了,这种题洛谷题解里竟然没有双指针的做法?首先考虑判断一个字符串\(b\)是否是另一个字符串\(a\)的子序列。这......
  • Alice and Hairdresser题解
    AliceandHairdresser第一眼线段树,第二眼好像可以直接用数组模拟。当一根头发长于\(l\),它再长多长其实都一样,所以不用开longlong。如果一根新的头发长到比\(l\)长,那可以分成以下几种情况:如果它左侧和右侧只有一个元素大于\(l\),那答案不变。如果左侧和右侧都大于......
  • ARC165F Make Adjacent
    D1a5y。记录\(x(1\lex\len)\)出现位置分别为\(l_x,r_x(l_x<r_x)\),讨论一下发现当两个数\(x,y\)满足\(l_x<l_y,r_x<r_y\)时操作后\(x\)一定出现在\(y\)前面,不然可以交换位置以达到更优步数。否则发现无论怎么操作发现都不影响答案。所以我们将\(x\)描述为平面上......
  • c# winform打开外部程序异常问题解决方案
    c#winform中打开外部程序的常规操作是使用Process类,此时,如果外部程序没有对路径的操作或其他路径文件的操作时,通常不会出现报错或异常;反之,会出现找不到路径或者直接抛出异常。此种情况主要是因为外部程序和当前程序不在一个路径下导致的,以下是解决方案:System.IO.Directory.Set......
  • yarn 出现 【 info There appears to be trouble with your network connection. Retr
    第一种解决方案#调整为taobao镜像源yarnconfigsetregistryhttps://registry.npm.taobao.org我用了没用,可以试试第二种解决方案要在项目根目录下创建后缀名为.yarnrc的文件,并设置network-timeout的值为600000,你可以按照以下步骤进行操作:打开文本编辑器,例如Note......
  • 【POJ 2488】A Knight‘s Journey 题解(深度优先搜索)
    背景骑士厌倦了一次又一次地看到同样的黑白方块,决定去旅行全世界每当骑士移动时,它是一个方向上的两个正方形和一个垂直于这个方向的正方形。骑士的世界就是他生活的棋盘。我们的骑士生活在一个棋盘上,这个棋盘的面积比普通的8*8棋盘小,但它仍然是矩形的。你能帮助这位冒险的骑士制......