首页 > 其他分享 >Atcoder Regular Contest 114 F - Permutation Division

Atcoder Regular Contest 114 F - Permutation Division

时间:2023-07-14 12:23:03浏览次数:38  
标签:Atcoder 排列 Contest int mid Division MAXN dp 字典

显然分成 \(k\) 段以后,最大化形成的排列的字典序的策略是将所有段按第一个元素的大小降序排列。

由于最终排列的字典序肯定 \(\ge\) 原排列的字典序,因此我们考虑最大化最终排列与原排列的 LCP,这部分就考虑二分答案,记 \(dp_i\) 表示以 \(p_1\) 开始 \(p_i\) 结尾的 LDS 的长度,那么考虑枚举 \(mid\) 所在的段的开始元素 \(i\),那么后面我们肯定会选最小的 \(k-dp_i\) 个元素,判断后面第 \(k-dp_i\) 大的数是否 \(\le p_i\) 即可。

最大化完 LCP 之后,由于我要让后面的段的第一个元素尽可能小,所以我们挑选前面 \(dp_i\) 最大的位置就行了。总复杂度 \(O(n\log n)\)。

const int MAXN=2e5;
const int INF=0x3f3f3f3f;
int n,k,a[MAXN+5],dp[MAXN+5],t[MAXN+5],vis[MAXN+5];
void add(int x,int v){for(int i=x;i;i-=(i&(-i)))chkmax(t[i],v);}
int query(int x){int ret=-INF;for(int i=x;i<=n;i+=(i&(-i)))chkmax(ret,t[i]);return ret;}
bool check(int mid){
	vector<int>vec;
	for(int i=mid+1;i<=n;i++)vec.pb(a[i]);
	sort(vec.begin(),vec.end());
	for(int i=1;i<=mid;i++)if(k-dp[i]<=vec.size()&&vec[k-dp[i]-1]<a[i])return 1;
	return 0;
}
int main(){
	scanf("%d%d",&n,&k);memset(t,192,sizeof(t));
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	dp[1]=1;add(a[1],1);
	for(int i=2;i<=n;i++)dp[i]=query(a[i])+1,add(a[i],dp[i]);
	for(int i=1;i<=n;i++)if(dp[i]>=k){
		for(int j=1;j<=n;j++)printf("%d%c",a[j]," \n"[j==n]);
		return 0;
	}
	int l=1,r=n-1,p=0;
	while(l<=r){
		int mid=l+r>>1;
		if(check(mid))p=mid,l=mid+1;
		else r=mid-1;
	}
	for(int i=1;i<=p;i++)printf("%d ",a[i]);
	int mn=k;vector<pii>vec;
	for(int i=p+1;i<=n;i++)vec.pb(mp(a[i],i));
	sort(vec.begin(),vec.end());
	for(int i=1;i<=p;i++)if(k-dp[i]<=vec.size()&&vec[k-dp[i]-1].fi<a[i])chkmin(mn,k-dp[i]);
	for(int i=0;i<mn;i++)vis[vec[i].se]=1;vis[n+1]=1;
	int cur=p+1;while(!vis[cur])printf("%d ",a[cur]),++cur;
	for(int i=mn-1;~i;i--){
		int pos=vec[i].se+1;
		while(!vis[pos])++pos;
		for(int j=vec[i].se;j<pos;j++)printf("%d ",a[j]);
	}printf("\n");
	return 0;
}

标签:Atcoder,排列,Contest,int,mid,Division,MAXN,dp,字典
From: https://www.cnblogs.com/tzcwk/p/arc114F.html

相关文章

  • AtCoder Regular Contest 164 A~C
    A题都没做出来(被自已菜晕A.TernaryDecompositionA-TernaryDecomposition(atcoder.jp)题意给定一个正整数\(N\),问是否存在\(K\)个整数,使得\(N=3^{m_1}+3^{m_2}+...+3^{m_k}\)思路首先对于一个正整数\(N\),最多有\(N\)个整数使得正式成立,即\(m_i\)全为0。再对\(N\)进行三......
  • SMU Summer 2023 Contest Round 3
    SMUSummer2023ContestRound3A.CurriculumVitae题意就是要求\(1\)后面不能有\(0\)的情况下的子序列最长长度,也就是求一个最长不下降子序列,不过由于这是个\(01\)序列,也可以分别做一个前缀和求出\(0\)的数量,后缀和求\(1\)的数量,最后跑一遍循环,找一个最大值即可,这里......
  • 【DP】DMOPC '21 Contest 8 P5 - Tree Building
    ProblemLink给定\(n,m\)和一个长为\(m\)的代价序列,对于一棵\(n\)个节点,每个节点度数不超过\(m\)的树,定义它的代价为\(\sum\limits_{i=1}^na_{deg_i}\)。求代价最小的树的代价。\(n\le10^9,m\le3000,1\lea_i\le10^9\)。首先一眼变成选出\(n\)个\(a\)的和为......
  • AtCoder Beginner Contest 161
    AtCoderBeginnerContest161https://atcoder.jp/contests/abc161这套不算难,但是sb我还是写不出来是为什么呢F是个妙妙题C-ReplacingIntegerWA了一次所以放上来#include<bits/stdc++.h>#definelllonglongusingnamespacestd;intmain(){lla,b;c......
  • AtCoder Grand Contest 012 D Colorful Balls
    洛谷传送门AtCoder传送门不错的题。bxEnder32k。我们发现交换有传递性,那么我们能交换就连边,答案是\(\prod\frac{(sz)!}{\prodc_i!}\),其中\(sz\)为连通块大小,\(c_i\)为这个连通块中第\(i\)种颜色出现次数。于是我们得到了一个\(O(n^2)\)的做法。发现很多遍是无用的......
  • AtCoder Regular Contest 164 E Segment-Tree Optimization
    洛谷传送门AtCoder传送门妙妙题。我们考虑如何方便地描述一棵广义线段树。不难想到使用断点描述,即对于一个结点\([l,r]\),它的左右儿子分别是\([l,mid],[mid+1,r]\),其中\(mid\in[l,r-1]\),然后把一层缩成一个\(2^{d-1}\)的序列,每一层都是上层对应结点的\(mid......
  • Atcoder ABC 309 F
    AtcoderABC309F题意n个盒子,长宽高为\(x,y,z,\)(长宽高是相对的,可以任意调换),问是否有一个盒子可以完全容纳另一个盒子,即存在一个\(A_i={x_i,y_i,z_i},A_j={x_j,y_j,z_j}\),使得\(x_i<x_j,y_i<y_j,z_i<z_j\)思路思考一个简单的问题:对于二元组\((x,y)\),我们怎么确定存在两......
  • AtCoder Beginner Contest 309 G Ban Permutation
    洛谷传送门AtCoder传送门前置知识:[ARC132C]AlmostSorted看\(\geX\)不顺眼,怎么办呢!直接容斥!钦定\(j\)个位置满足\(|P_i-i|<X\),其余任意,就转化成了[ARC132C]AlmostSorted。具体一点就是,你设\(f_{i,j,S}\)表示前\(i\)位有\(j\)个位置满足\(|P_i-i|<......
  • atcoder绿题选做
    ABC305:E  https://atcoder.jp/contests/abc305/tasks/abc305_e题意:给定一个无向图,给定k个守卫,每个守卫有h[i]的耐力值,如果是一个在图中是被保护的要满足和守卫的距离至少为h[i],让你升序打印所有被守卫的点解题思路:可以从守卫出发,看守卫在可以走的情况下最远走到哪,最后统计......
  • SMU Summer 2023 Contest Round 2
    SMUSummer2023ContestRound2A.TreasureHunt当\(x1-x2\)的差值与\(y1-y2\)的差值都能被\(x,y\)整除时,且商之和为2的倍数就一定可以到达#include<bits/stdc++.h>#defineendl'\n'#defineintlonglong#defineinf0x3f3f3f3fusingnamespacestd;constintN......