首页 > 其他分享 >例题两则(不无聊的子序列,HNOI2016序列)

例题两则(不无聊的子序列,HNOI2016序列)

时间:2023-08-25 10:13:52浏览次数:29  
标签:pre ch suc int text HNOI2016 序列 例题 leqslant

分享例题两则主要是分享一种 \(\text{trick}\) 。

\(\text{UVA1608}\)

题目描述

给定一个长度为 \(n\) 的序列 \(a\) ,如果 \(a\) 的每一个子串都存在至少一个元素只出现了一次,输出 \(\text{Non-boring}\) 。反之,输出 \(\text{Boring}\) 。\(n \leqslant 2\times 10^5\) 。

思路点拨

类似于这样的题目,可以按照我下述的方法进行思考。

对于一个元素而言,我们记录上一个与他值相同的元素的下标 \(pre_i\) ,下一个与他元素值相同的下标 \(suc_i\) 。那么对于左端点在 \([pre_i+1,i]\) 并且右端点在 \([i,suc_i-1]\) 的区间就是满足题目要求的。我们考虑建立一个平面直角坐标系,以区间的左端点作为横坐标,以区间的右端点作为纵坐标。那么一个元素 \(a_i\) 产生的贡献就可以看作一个以 \((pre_i+1,i)\) 为左下角,以 \((i,suc_i-1)\) 为右上角的矩形。

如果对于点 \((l,r) (1 \leqslant l \leqslant r\leqslant n)\) 都被至少一个矩形覆盖,我们可以判断为有解。现在我们需要使用某种方法来加速这一过程,并且不难想到使用扫描线算法。如果这些矩形的面积并为 \(\dfrac{n(n+1)}{2}\) ,那么我们就认为是有解的。

时间复杂度 \(O(T\times n \log n)\) ,可以通过。

\(\text{code}\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
inline int read(){
	int x=0,f=1;
	char ch=getchar();
	while(ch<'0'||ch>'9'){
		if(ch=='-') f=-f;
		ch=getchar(); 
	} 
	while(ch>='0'&&ch<='9'){
		x=x*10+ch-'0';
		ch=getchar();
	}
	return x*f;
} 
const int MAXN=4e5+10;
int T,n,a[MAXN];
map<int,int> pre,suc;
int lef[MAXN],rig[MAXN];
struct node{
	int l,r,h,w;
	bool friend operator<(const node &A,const node &B){
		return A.h<B.h;
	}
}line[MAXN];
struct seg{
	int l,r;
	int sum,len;
}t[MAXN<<3];
void pushup(int i){
	if(t[i].sum) t[i].len=t[i].r-t[i].l+1;
	else t[i].len=t[i<<1].len+t[i<<1|1].len;
}
void build(int i,int l,int r){
	t[i].l=l,t[i].r=r;
	t[i].sum=t[i].len=0;
	if(l==r) return ;
	int mid=(l+r)>>1;
	build(i<<1,l,mid);
	build(i<<1|1,mid+1,r);
}
void update(int i,int l,int r,int w){
	if(l<=t[i].l&&t[i].r<=r){
		t[i].sum+=w;
		pushup(i);
		return ;
	}
	if(t[i].l>r||t[i].r<l) return ;
	update(i<<1,l,r,w);
	update(i<<1|1,l,r,w);
	pushup(i);
}
signed main(){
	T=read();
	while(T--){
		n=read();
		for(int i=1;i<=n;i++) a[i]=read();
		pre.clear(),suc.clear();
		for(int i=1;i<=n;i++){
			lef[i]=pre[a[i]];
			if(!lef[i]) lef[i]=0;
			pre[a[i]]=i;
		}
		for(int i=n;i;i--){
			rig[i]=suc[a[i]];
			if(!rig[i]) rig[i]=n+1;
			suc[a[i]]=i;
		}
		for(int i=1;i<=n;i++){
			//(lef[i]+1,i),(i,rig[i]-1)
			line[(i<<1)-1].l=line[i<<1].l=lef[i]+1;
			line[(i<<1)-1].r=line[i<<1].r=i;
			line[(i<<1)-1].h=i,line[i<<1].h=rig[i];
			line[(i<<1)-1].w=1,line[i<<1].w=-1;
		}
		sort(line+1,line+n*2+1);
		build(1,1,n);
		int ans=0,pos=1;
		for(int i=1;i<=n;i++){
			while(pos<=n*2&&line[pos].h<=i){
				update(1,line[pos].l,line[pos].r,line[pos].w);
				pos++;
			}
			ans+=t[1].len;
		}
		if(ans==n*(n+1)/2) cout<<"non-boring"<<endl;
		else cout<<"boring"<<endl;
	} 
	return 0;
}

标签:pre,ch,suc,int,text,HNOI2016,序列,例题,leqslant
From: https://www.cnblogs.com/Diavolo/p/17656130.html

相关文章

  • 【LeetCode动态规划#15】最长公共子序列II
    最长公共子序列(二)描述给定两个字符串str1和str2,输出两个字符串的最长公共子序列。如果最长公共子序列为空,则返回"-1"。目前给出的数据,仅仅会存在一个最长的公共子序列数据范围:0≤∣���1∣,∣���2∣≤20000≤∣str1∣,∣str2∣≤2000要求:空间复杂度�(�2)O(n2),时间复杂度�(�2)O(n2)......
  • 【剑指Offer】41、和为S的连续正数序列
    【剑指Offer】41、和为S的连续正数序列题目描述:小明很喜欢数学,有一天他在做数学作业时,要求计算出9~16的和,他马上就写出了正确答案是100。但是他并不满足于此,他在想究竟有多少种连续的正数序列的和为100(至少包括两个数)。没多久,他就得到另一组连续正数和为100的序列:18,19,......
  • 多元时间序列 | Matlab粒子群算法优化深度置信网络(PSO-DBN)多变量时间序列预测
    ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,matlab项目合作可私信。......
  • java序列化
    序列化和反序列化序列化:把对象转换为字节序列的过程称为对象的序列化.反序列化:把字节序列恢复为对象的过程称为对象的反序列化.什么时候需要用到序列化和反序列化将内存中的对象持久化到磁盘、数据库或网络传输对象深拷贝Serializable接口在Java中实现了Serializab......
  • 由P7914括号序列(A题)引发的关于区间DP的思考
    和CF149DColoringBrackets(B题)一样,都是关于括号的区间DP。在B题中,有一个细节,就是在枚举断点时枚举到第一个就要break,这是为了使每种方案只贡献一次,防止一种方案中有多个符合条件的断点。此题中,因为序列的字符是不变的,所以直接break就行了。但是在A题中,情况变得比较复杂,比如一......
  • FastJson不成想还有个版本2啊:序列化大字符串报错
    背景发现陷入了一个怪圈,写文章的话,感觉只有大bug或比较值得写的内容才会写,每次一写就是几千字,争取写得透彻一些,但这样,我也挺费时间,读者也未必有这么多时间看。我想着,日常遇到的小bug、平时工作中的一些小的心得体会,都还是可以写写,这样也才是最贴近咱们作为一线开发生活的,也不必......
  • 利用 XGBoost 进行时间序列预测
    推荐:使用NSDT场景编辑器助你快速搭建3D应用场景XGBoost应用程序的常见情况是分类预测(如欺诈检测)或回归预测(如房价预测)。但是,也可以扩展XGBoost算法以预测时间序列数据。它是如何工作的?让我们进一步探讨这一点。时间序列预测数据科学和机器学习中的预测是一种技术,用于根据一......
  • hdu 1003 最大最长上升子序列 贪心
    要想找到符合条件的序列,我们应该有以下条件 一个数重头开始遍历相加,如果这个数大于0的话,继续加后面的数,如果小于0的话,重后面的数开始重新遍历;这个过程中保证了大数一定会出现,所以应该找出大数;sum大于0的话,与后面的数相加有可能是最大数;如果小于0,则,重新开始会比以前的数更大;一下是......
  • hdu 1003 最大最长子序列 dp
    我的dp思路是记b[j]表示到到j位,最大最长的子序列的和则可得状态转移方程b[j]=max(b[j-1]+a[j],a[j]);因为每个数都有两种状态,要么和前面相连,要么自己相连;让后再比较出来最大值;一下是我的代码#include<stdio.h>#include<stdlib.h>#include<stdlib.h>#include<math.h>#includ......
  • Python基础入门学习笔记 016 序列!序列!
    •列表、元组和字符串的共同点–都可以通过索引得到每一个元素–默认索引值总是从0开始–可以通过分片的方法得到一个范围内的元素的集合–有很多共同的操作符(重复操作符、拼接操作符、成员关系操作符)使用list方法 元组转换为列表 max()返回序列或者参数集合中的最大......