uva1608(Non-boring sequences)

题意:如果一个序列的任意连续子序列中至少有一个只出现一次的元素,则称这个序列是不无聊的。判断一个长度为n(n<=200000)的序列是不是无聊的。

解法:搞个map记录每个数前一个数的位置,判断以每个数结尾的所有区间是否合法,其中用到线段树访问区间最小值。

代码:

/******************************************************
* @author:xiefubao
*******************************************************/
#pragma comment(linker, "/STACK:102400000,102400000")
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <queue>
#include <vector>
#include <algorithm>
#include <cmath>
#include <map>
#include <set>
#include <stack>
#include <string.h>
//freopen ("in.txt" , "r" , stdin);
using namespace std;

#define eps 1e-8
#define zero(_) (abs(_)<=eps)
const double pi=acos(-1.0);
typedef long long LL;
const int Max=200010;
const LL INF=0x3FFFFFFF;
int n;
int num[Max];
int pre[Max];
map<int,int> maps;
struct node
{
    int l,r;
    node* left,* right;
    int ma;
} nodes[Max*3];
int tot=0;
void build(node* p,int l,int r)
{
    p->l=l;
    p->r=r;
    p->ma=INF;
    if(l==r)
        return ;
    int middle=(l+r)>>1;

    tot++;
    p->left=nodes+tot;
    build(p->left,l,middle);

    tot++;
    p->right=nodes+tot;
    build(p->right,middle+1,r);
}
void down(node* p)
{
    p->ma=min(p->left->ma,p->right->ma);
}
void update(node* p,int index,int value)
{
    if(p->l==p->r&&p->l==index)
    {
        p->ma=value;
        return ;
    }
    int middle=(p->l+p->r)>>1;
    if(index<=middle)
        update(p->left,index,value);
    else
        update(p->right,index,value);
    down(p);
}
int query(node* p,int l,int r)
{
    if(p->l==l&&p->r==r)
        return p->ma;
    int middle=(p->r+p->l)>>1;
    if(r<=middle)
        return query(p->left,l,r);
    else if(l>middle)
        return query(p->right,l,r);
    else
        return min(query(p->left,l,middle),query(p->right,middle+1,r));
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        tot=0;
        maps.clear();
        scanf("%d",&n);
        build(nodes,1,n);
        for(int i=1; i<=n; i++)
            scanf("%d",num+i);
        reverse(num+1,num+n+1);
        for(int i=1; i<=n; i++)
            pre[i]=maps[num[i]],maps[num[i]]=i;
        bool flag=0;
        for(int i=1; i<=n; i++)
        {
            if(pre[i]!=0)
                update(nodes,pre[i],pre[i]);
            int left=pre[i],right=i;
            while(left>0)
            {
                int pr;
                if(left+1<=right-1)
                    pr=query(nodes,left+1,right-1);
                if(left+1>right-1||pr>=left)
                {
                    flag=1;
                    break;
                }
                right=left;
                left=pr;
            }
            if(flag)
                break;
            update(nodes,i,pre[i]);
        }
        if(flag)
            puts("boring");
        else
            puts("non-boring");
    }
    return 0;
}
/*
ababababa
*/
时间: 2024-10-27 10:48:02

uva1608(Non-boring sequences)的相关文章

【BZOJ4059】[Cerc2012]Non-boring sequences 分治

[BZOJ4059][Cerc2012]Non-boring sequences Description 我们害怕把这道题题面搞得太无聊了,所以我们决定让这题超短.一个序列被称为是不无聊的,仅当它的每个连续子序列存在一个独一无二的数字,即每个子序列里至少存在一个数字只出现一次.给定一个整数序列,请你判断它是不是不无聊的. Input 第一行一个正整数T,表示有T组数据.每组数据第一行一个正整数n,表示序列的长度,1 <= n <= 200000.接下来一行n个不超过10^9的非负整数,表示这个

BZOJ 4059: [Cerc2012]Non-boring sequences ( )

要快速在一段子序列中判断一个元素是否只出现一次 , 我们可以预处理出每个元素左边和右边最近的相同元素的位置 , 这样就可以 O( 1 ) 判断. 考虑一段序列 [ l , r ] , 假如我们找到了序列中唯一元素的位置 p , 那我们只需检查 [ l , p - 1 ] & [ p + 1 , r ] 是否 non-boring 即可 . 如何检查 序列 [ l , r ] 呢 ? 假如从左往右或者从右往左找 , 最坏情况下是 O( n ) , 总时间复杂度会变成 O( n² ) ; 假如我们从

poj 1776 Task Sequences

http://poj.org/problem?id=1776 题意: 有一个机器要完成N个作业, 给你一个N*N的矩阵, M[i][j]=1,表示完成第i个作业后不用重启机器,继续去完成第j个作业 M[i][j]=0,表示如果做完第i个作业,想要继续去做第j个作业,那么必须重启机器 对于任意两个作业都有M[i][j] = 1或者M[j][i] = 1. 求出完成这N个作业启动机器的最少次数,以及每次启动完成作业的数量和这些作业的顺序 初始时机器处于关闭状态. 将M当做图,就是找最少的路径条数覆盖

●UVA 1608 Non-boring sequences

题链: https://vjudge.net/problem/UVA-1608#author=chenchonghan题解: 分治 如果一个区间[l,r]里面在p位置出现了一个只出现一次的元素,(如果不存在该元素,该区间就是boring的) 那么必然包含p的子区间都是non-boring的. 即如果存在boring的区间,必然是[l,p-1],[p+1,r]的子区间. 所以继续递归处理上面两个区间即可. (判断某个元素是否在区间里只出现一次,只需考虑它左边第一个与它相同的元素或它右边第一个相同的

Boring Class HDU - 5324 (CDQ分治)

Mr. Zstu and Mr. Hdu are taking a boring class , Mr. Zstu comes up with a problem to kill time, Mr. Hdu thinks it’s too easy, he solved it very quickly, what about you guys? Here is the problem: Give you two sequences L1,L2,...,Ln and R1,R2,...,Rn. Y

[LeetCode]Repeated DNA Sequences

题目:Repeated DNA Sequences 给定包含A.C.G.T四个字符的字符串找出其中十个字符的重复子串. 思路: 首先,string中只有ACGT四个字符,因此可以将string看成是1,3,7,20这三个数字的组合串: 并且可以发现{ACGT}%5={1,3,2,0};于是可以用两个位就能表示上面的四个字符: 同时,一个子序列有10个字符,一共需要20bit,即int型数据类型就能表示一个子序列: 这样可以使用计数排序的思想来统计重复子序列: 这个思路时间复杂度只有O(n),但是

BZOJ 4059 [Cerc2012]Non-boring sequences(启发式分治)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=4059 [题目大意] 一个序列被称为是不无聊的,仅当它的每个连续子序列存在一个独一无二的数字, 即每个子序列里至少存在一个数字只出现一次. 给定一个整数序列,请你判断它是不是不无聊的. [题解] 预处理每个元素上一次出现位置和下一个出现位置, 我们发现对于一个子序列[L,R]来说, 如果存在pre[i]<L&&nxt[i]>R那么这个子序列一定是满足条件的, 否则就不

hihoCoder 1430 : A Boring Problem(一琐繁题)

hihoCoder #1430 : A Boring Problem(一琐繁题) 时间限制:1000ms 单点时限:1000ms 内存限制:256MB Description - 题目描述 As a student of the school of electronics engineering and computer science in Peking University, Kyle took the course named Advanced Algebra in his freshma

Repeated DNA Sequences

package cn.edu.xidian.sselab.hashtable; import java.util.ArrayList;import java.util.HashSet;import java.util.List;import java.util.Set; /** *  * @author zhiyong wang * title: Repeated DNA Sequences * content: *  All DNA is composed of a series of nuc