首页 > 其他分享 >题解【CF1436E Complicated Computations】

题解【CF1436E Complicated Computations】

时间:2022-09-27 09:56:10浏览次数:84  
标签:node return Computations 题解 序列 Complicated 区间 MAXN mex

CF1436E Complicated Computations
解题报告。
不一定更好的阅读体验

对于一个数 \(x\),考虑什么条件 \(x\) 可以作为答案。

首先要满足 \(\forall y\in [1,x)\),\(y\) 都不能作为答案,因为最终我们是取的 mex。

其次,原序列任何一个连续子序列的 mex 都不可能为 \(x\)。

第一个条件我们只需要顺着枚举 \(x\) 即可,考虑如何解决第二个条件限制。

我们把 \(x\) 在原序列出现的位置都提出来,这样会把原序列分割成若干不包含 \(x\) 的极长子区间。

任何一个包含 \(x\) 的子区间的 mex 都不可能为 \(x\),所以我们只需要检查分割出来的所有子区间中是否存在一个区间的 mex 是 \(x\),只要有就不合法。

对于每一个 \(x\) 这些子区间显然是可以暴力处理的出来的,因为区间总数是不超过 \(O(n)\) 个的。

于是现在就变成区间求 mex 的问题,可以考虑可持久化权值线段树,

具体的,对于一个询问区间 \([l,r]\),我们提出以 \([1,r]\) 这个序列建出的的权值线段树,维护每一个数最后出现的位置,若一个数最后出现的位置小于 \(l\),说明这个数可能作为 mex,而真正的 mex 是这些数的 \(\min\)。

这就典了啊,线段树上二分乱杀即可。有限走左子树,然后走右子树。

时间复杂度 \(\Theta(n\log n)\),比莫队套值域分块快多了。

代码(自认为写得比较好看):

const int MAXN(1e5+10);

int n,m,a[MAXN];
bool flag[MAXN];

vector<int>G[MAXN];
struct node{int l,r,v;};
node q[MAXN<<1];


inline void newquery(int l,int r,int v){if(l>r)return;q[++m].l=l;q[m].r=r,q[m].v=v;return;}
inline bool cmp(node x,node y){return x.r<y.r;}

int rt[MAXN];

struct Segment_Tree
{
	struct T{int ls,rs,val;};
	T tree[MAXN*30];
	int tot;

	inline int lc(int u){return tree[u].ls;}
	inline int rc(int u){return tree[u].rs;}

	inline void push_up(int u)
	{
		tree[u].val=Min(tree[tree[u].ls].val,tree[tree[u].rs].val);
		return;
	}

	inline void update(int&u,int pre,int l,int r,int p,int k)
	{
		u=++tot;
		tree[u]=tree[pre];
		if(l==r)
		{
			tree[u].val=k;
			return;
		}
		int mid=(l+r)>>1;
		if(p<=mid) update(tree[u].ls,tree[pre].ls,l,mid,p,k);
		else update(tree[u].rs,tree[pre].rs,mid+1,r,p,k);
		push_up(u);
		return;
	}

	inline int query(int u,int l,int r,int L)
	{
		if(l==r) return l;
		int mid=(l+r)>>1;
		if(tree[lc(u)].val<L) return query(lc(u),l,mid,L);
		else return query(rc(u),mid+1,r,L);
	}
};
Segment_Tree seg;

int main()
{
	n=read();
	rep(i,1,n) a[i]=read(),G[a[i]].push_back(i);
	rep(i,1,n)
	{
		rep(j,0,(int)G[i].size()-1)
		{
			if(j==0) newquery(1,G[i][j]-1,i);
			else newquery(G[i][j-1]+1,G[i][j]-1,i);
		}
		if(G[i].size()) newquery(G[i][G[i].size()-1]+1,n,i);
	}
	rep(i,1,n)
		seg.update(rt[i],rt[i-1],1,n+1,a[i],i);
	rt[n+1]=rt[n];
	rep(i,1,m)
	{
		int l=q[i].l,r=q[i].r,v=q[i].v;
		if(seg.query(rt[r],1,n+1,l)==v) flag[v]=true; 
	}
	rep(i,1,n+2) if(seg.query(rt[n+1],1,n+1,1)==i) flag[i]=true;
	rep(i,1,n+2) if(!flag[i])
	{
		printf("%d\n",i);
		return 0;
	}
    return 0;
}
/*
Date : 2022/9/27
Author : UperFicial
Start coding at : 7:05
finish debugging at : 9:34
*/

标签:node,return,Computations,题解,序列,Complicated,区间,MAXN,mex
From: https://www.cnblogs.com/UperFicial/p/16733491.html

相关文章

  • SpringBoot+Mybatis-Plus 数据表字段是关键字的问题解决
    如果字段名是关键字,用mybatisplus时会报以下错误:badSQLgrammar[];nestedexceptionisjava.sql.BatchUpdateException:ORA-01747:user.table.column,table.column......
  • 力扣算法第1题--两数之和(暴力题解&优化题解)
    两数之和题目描述:给定一个整数数组nums 和一个整数目标值target,请你在该数组中找出和为目标值target 的那 两个 整数,并返回它们的数组下标。你可以假设每种输......
  • P2044 随机数生成器 题解
    这么标准的不动点居然只有一篇不动点题解?而且唯一的不动点题解关于不动点的描述还是错的?所以,来写一篇题解讲讲,MO中是怎么弄这种一阶线性递推式的。单个数,虽然省常数,却......
  • P6835 [Cnoi2020]线形生物 题解
    通过这道题可以看出来pz根本不会期望考虑期望线性性质,设\(E_{x\toy}\)表示从\(x\)走到\(y\)的期望步数,那么有\(E_{1\ton+1}=\sum_{i=1}^nE_{i\toi+1}\),因此考......
  • P2569 [SCOI2010]股票交易 题解
    设\(f_{i,j}\)表示第1天至第\(i\)天,手上有\(j\)股股票时拥有的最多钱。考虑转移,首先就有\(f_{i,j}=-j\timesap_i\)即单纯买入,然后由转移方程定义有\(f_{i,j}=......
  • CF1155D 题解
    题目传送门题目分析说实话,第一眼这题以为是贪心...(事实上我看所有动态规划都像贪心)。然后接着发现贪心明显做不了,又看见最大子段和,很容易联想到\(\text{dp}\)。在设计......
  • 牛客题解 贝伦卡斯泰露
    链接:https://ac.nowcoder.com/acm/problem/14132来源:牛客网题解作者岛田小雅子序列的概念,需要区别于子串。本来以为是道DP题,看了下范围发现爆搜好像问题也不是很大......
  • 线段树学习笔记(基础&进阶)(一) | P3372 【模板】线段树 1 题解
    什么是线段树线段树是一棵二叉树,每个结点存储需维护的信息,一般用于处理区间最值、区间和等问题。线段树的用处对编号连续的一些点进行修改或者统计操作,修改和统计的复杂......
  • AGC028C Min Cost Cycle 题解
    考虑将\(\min(a_i,b_j)\)转化为任意选择\(a_i,b_j\),因为多出来的不合法状态答案一定不会变小。注意到一个合法的行走方案对于\(a_i,b_j\)的选择只有如下两种情况之一......
  • 题解【CF209C Trails and Glades】
    CF209CTrailsandGlades解题报告图论基础题。考虑一张无向联通图存在欧拉回路的条件是什么:每一个点的度数均为偶数。但这个条件的前提是连通图,那么我们可以考虑......