首页 > 其他分享 >CF2031D 题解

CF2031D 题解

时间:2024-11-16 08:49:01浏览次数:1  
标签:ch CF2031D int 题解 mn pos 区间 mx

原题链接

最后悔的一集,感觉 D \(<\) everything。

考虑由确定的点推出其他点的答案,发现最高点的答案是确定的,设其位置为 \(x\)。

然后根据题目定义,发现可以分成 \([1,x-1],[x,n]\) 两个区间,\([x,n]\) 答案均为 \(h_x\)。

对于 \([1,x-1]\) 区间,我们找到第一个 \(>[x,n]\) 区间最小值的位置,设其为 \(y\),则 \([y,x-1]\) 答案也为 \(h_x\)。

简证:\(y\) 能跳到 \([x,n]\) 区间最小值的位置,然后跳到 \(x\),对于 \(z>y\),若其高度 \(>h_y\),也可以跳到 \([x,n]\) 区间, 若其高度 \(<h_y\),则可以跳到 \(y\),进一步跳到 \(x\)。

然后我们再去处理 \([1,y-1]\) 区间即可。

注意若 \([1,x-1]\) 区间最大值也 \(<[x,n]\) 最小值,那么我们找出 \([1,x-1]\) 区间最大值,重复上述过程。

找区间最大值位置,st 表即可。

答案和最小值暴力找即可,找第一个\(>[x,n]\) 区间最小值的位置,预处理前缀最大值,然后二分。

时间复杂度 \(O(nlogn)\)。

#include<bits/stdc++.h>
using namespace std;
#define rd read()
#define gc getchar()
#define dg(ch) isdigit(ch)
#define _mul(x) ((x<<3)+(x<<1))
#define ll long long
#define FOR(i,j,k) for(int i=j;i<=k;i++)
#define ROF(i,j,k) for(int i=j;i>=k;i--)
int read(){int x=0,f=1;char ch=gc;while(!dg(ch)){if(ch=='-')f=-1;ch=gc;}while(dg(ch)){x=_mul(x)+(ch^48),ch=gc;}return x*f;}
const int N=5e5+10,INF=1e9;
int T,n,mx[N],f[N][20],a[N],ans[N],mxn,mn;
int cmp(int x,int y){return a[x]>a[y]?x:y;}
int query(int l,int r){
	int k=log2(r-l+1);
	return cmp(f[l][k],f[r-(1<<(k))+1][k]);
}
void cal(int r){
	if(r<1) return;
	int res=0,L=1,R=r;
	while(L<=R){
		int mid=(L+R)>>1;
		if(mx[mid]>mn) R=mid-1,res=mid;
		else L=mid+1;
	}
	if(res==0){
		int pos=query(1,r);FOR(i,pos,r) ans[i]=a[pos],mn=min(mn,a[i]);
		mxn=a[pos],cal(pos-1);return;
	}
	else{
		FOR(i,res,r) ans[i]=mxn,mn=min(mn,a[i]);
		cal(res-1);
	}
}
void solve(){
	FOR(i,1,n) mx[i]=0,a[i]=0,ans[i]=0;mn=INF,mxn=0;
	FOR(i,1,n) FOR(j,0,20) f[i][j]=0;
	n=rd;FOR(i,1,n) a[i]=rd,mx[i]=max(mx[i-1],a[i]),f[i][0]=i;
	int t=log2(n)+1;
	FOR(i,1,t-1) for(int j=1;(j+(1<<i))-1<=n;j++) f[j][i]=cmp(f[j][i-1],f[j+(1<<i-1)][i-1]);
	int pos=query(1,n);FOR(i,pos,n) ans[i]=a[pos],mn=min(mn,a[i]);
	mxn=a[pos],cal(pos-1);
	FOR(i,1,n) printf("%d ",ans[i]);cout<<'\n';
}
int main(){
	T=rd;
	while(T--) solve();
	return 0;
}

标签:ch,CF2031D,int,题解,mn,pos,区间,mx
From: https://www.cnblogs.com/summ1t/p/18548972

相关文章

  • 读数据质量管理:数据可靠性与数据质量问题解决之道05数据标准化
    1. 批处理1.1. 批处理在一段时间内收集数据,然后将大量数据“批处理”在离散的数据包中1.2. 直到20世纪10年代中期,批处理都是处理分析型数据最常用的方法1.3. 批处理比流处理要便宜得多,即使是对时间要求最苛刻的处理需求也足以满足1.4. 批处理是经过时间考验的标准,并且仍......
  • POI 四题题解
    P3434[POI2006]KRA-TheDisks考场上不知道在想什么,把\(O(n)\)正解改成\(O(n\mathrm{log}n)\)的了。关于\(O(n\mathrm{log}n)\)做法很多,我只讲我的。直接二分盘子会在哪里卡住,二分范围是\(1\simlst\)。\(lst\)表示上一个盘子卡住的位置。\(\mathrm{Code}\)#includ......
  • CF1909F1 Small Permutation Problem (Easy Version) 题解
    CF1909F1SmallPermutationProblem(EasyVersion)题解直接莽做显然不好统计。考虑统计每一次\(i\)的变化有多少种方案数来匹配,也就是对\(a\)数组差分。考虑到对于\(a_i\),只有\([1,i]\)里的数会对\(a_i\)有影响。注意到\(p\)形成一个排列,于是我们不妨考虑此时\(p......
  • [题解]P5687 [CSP-S2019 江西] 网格图
    P5687[CSP-S2019江西]网格图简单来说题目就是给定一个\(n\timesm\)的网格图,同行边权相同,同列边权相同,求该网格图的最小生成树。根据Kruskal算法的贪心思想,我们要优先选择权值尽可能小的行,并将这条边应用于尽可能多的列。列方向同理。为了保证最终生成树的连通性,我们显然要......
  • 题解: BZOJ3517 翻硬币
    ProblemLinkBZOJ3517翻硬币题目描述有一个\(n\)行\(n\)列的棋盘,每个格子上都有一个硬币,且\(n\)为偶数。每个硬币要么是正面朝上,要么是反面朝上。每次操作你可以选定一个格子\((x,y)\),然后将第\(x\)行和第\(y\)列的所有硬币都翻面。求将所有硬币都变成同一个面最少......
  • ISCTF比赛PWN题前三题题解
    萌新第一次发布题解,如有错误还请各位大佬指出。本次比赛个人pwn出题情况,还是太菜了,后面四题基本看不懂girlfriend解题思路:利用填充覆盖检查位置,绕过前面admin检查,进入vuln函数,经过动调发现,每次数据存放位置,从而达到提权解题过程存在后门函数read可以读取0x30大小,观察buf......
  • P9870 [NOIP2023] 双序列拓展 题解
    P9870[NOIP2023]双序列拓展题解NOIP2023T3,特殊性质题。什么是特殊性质题?就是题目给出了你极其神秘的性质,从而引导你想出正解。本篇题解将从部分分的角度,一步步讲述部分分与正解的关系。这样看的话,本题会变得十分简单。\(\text{Task}1∼7,O(Tnm)\)简化题意其实就是要求......
  • Toyota Programming Contest 2024#11(AtCoder Beginner Contest 379)题解总结
    AtCoderBeginnerContest379Rated:\(770\)A-Cyclic简单模拟。B-Strawberries字符串模拟,substr函数秒了C-Repeating中等模拟。思路:判断是否合法很简单,重点在计算花费。假设我们是\(0\)号点有\(N\)个棋子,然后移动到每个点上,显然花费为\(\frac{N(N+1)}{......
  • [CEOI2023] The Ties That Guide Us 题解
    Description你用销售机器人的利润雇佣了一名助手,现在你准备好去拿走装有CEOI奖章的保险箱了。保险箱位于一所由\(n\)个房间所组成的大学建筑内,这些房间由\(n-1\)扇门连接。每个房间都可以从其他任何房间到达,且每个房间最多与\(3\)扇门相连。你和你的助手都有描述建筑物......
  • P1437 敲砖块 题解
    题意在一个凹槽中放置了\(n\)层砖块、最上面的一层有\(n\)块砖,从上到下每层依次减少一块砖。每块砖都有一个分值,敲掉这块砖就能得到相应的分值,如下图所示:14154323333376221311222331如果你想敲掉第\(i\)层的第\(j\)块砖的话,若\(i=1\),你可以直接......