• 【刷题】BZOJ 4059 [Cerc2012]Non-boring sequences


    Description

    我们害怕把这道题题面搞得太无聊了,所以我们决定让这题超短。一个序列被称为是不无聊的,仅当它的每个连续子序列存在一个独一无二的数字,即每个子序列里至少存在一个数字只出现一次。给定一个整数序列,请你判断它是不是不无聊的。

    Input

    第一行一个正整数T,表示有T组数据。每组数据第一行一个正整数n,表示序列的长度,1 <= n <= 200000。接下来一行n个不超过10^9的非负整数,表示这个序列。

    Output

    对于每组数据输出一行,输出"non-boring"表示这个序列不无聊,输出"boring"表示这个序列无聊。

    Sample Input

    4
    5
    1 2 3 4 5
    5
    1 1 1 1 1
    5
    1 2 3 2 1
    5
    1 1 2 1 1

    Sample Output

    non-boring
    boring
    non-boring
    boring

    Solution

    考虑分治
    处理出每个位置的数的上一次出现位置与下一次出现位置,一段区间 (l,r) ,如果其中 (x) 位置上的数满足 (pre[x]<l) 并且 (nxt[x]>r) ,那么说明 (l,r) 这段区间内的所有子区间只要跨过了 (x) 位置,那么就满足要求,所以就继续分成两端区间 ([l,x))((x,r]) 进行判断
    朴素的,是一个一个枚举 (x) ,但这样复杂度是错误的,因为这样的分治,并不均匀,不能保证最后是 (log)
    但是考虑变换枚举方法,双向枚举,从两边往中间枚举,这样复杂度就对了。置于为什么,可以将这个分治的过程倒过来当成合并来思考,即每次合并两个区间的复杂度是小的那段区间的长度,这不就是启发式合并吗?所以复杂度正确
    代码并不难,主要难在分治以及复杂度分析

    #include<bits/stdc++.h>
    #define ui unsigned int
    #define ll long long
    #define db double
    #define ld long double
    #define ull unsigned long long
    const int MAXN=200000+10;
    int T,n,a[MAXN],pre[MAXN],nxt[MAXN];
    std::map<int,int> M;
    template<typename T> inline void read(T &x)
    {
    	T data=0,w=1;
    	char ch=0;
    	while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
    	if(ch=='-')w=-1,ch=getchar();
    	while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
    	x=data*w;
    }
    template<typename T> inline void write(T x,char ch='')
    {
    	if(x<0)putchar('-'),x=-x;
    	if(x>9)write(x/10);
    	putchar(x%10+'0');
    	if(ch!='')putchar(ch);
    }
    template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
    template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
    template<typename T> inline T min(T x,T y){return x<y?x:y;}
    template<typename T> inline T max(T x,T y){return x>y?x:y;}
    inline bool solve(int l,int r)
    {
    	if(r<=l)return true;
    	int p=l,q=r;
    	for(register int p=l,q=r;p<=q;++p,--q)
    		if(pre[p]<l&&nxt[p]>r)return solve(l,p-1)&&solve(p+1,r);
    		else if(p!=q&&pre[q]<l&&nxt[q]>r)return solve(l,q-1)&&solve(q+1,r);
    	return false;
    }
    int main()
    {
    	read(T);
    	while(T--)
    	{
    		int n;read(n);
    		for(register int i=1;i<=n;++i)read(a[i]);
    		M.clear();
    		for(register int i=1;i<=n;++i)pre[i]=M[a[i]],M[a[i]]=i;
    		M.clear();
    		for(register int i=n;i>=1;--i)nxt[i]=M[a[i]]?M[a[i]]:n+1,M[a[i]]=i;
    		if(!solve(1,n))puts("boring");
    		else puts("non-boring");
    	}
    	return 0;
    }
    
  • 相关阅读:
    找最后的字符
    统计指定数字和
    班级排队
    python编程题
    python函数题
    2019.6.24-2019.6.28(实训数据结构)3.数组编码求解问题
    2019.6.24-2019.6.28(实训数据结构)1.商品管理系统实训c++(实现的基本功能:初始化,创建表,插入,删除,更新,查询,链表数据与文件之间的转换)
    2019.6.24-2019.6.28(实训数据结构) 2.背包问题
    2019.6.24-2019.6.28(实训数据结构)4.树和二叉树应用项目
    2019.6.24-2019.6.28(实训数据结构)5.图的邻接矩阵表示
  • 原文地址:https://www.cnblogs.com/hongyj/p/9517972.html
Copyright © 2020-2023  润新知