UVa 1608 (分治 中途相遇) Non-boring sequences

预处理一下每个元素左边和右边最近的相邻元素。

对于一个区间[l, r]和区间内某一个元素,这个元素在这个区间唯一当且仅当左右两边最近的相邻元素不在这个区间内。这样就可以O(1)完成查询。

首先查找整个字符串是否有唯一元素,如果没有则整个序列是无聊的。

有的话,假设这个唯一元素下标是p,那么如果子序列[0, p-1]和[p+1, n-1]是不无聊的,那么这个序列就是不无聊的。

关于查找的话,如果只从一端查找唯一元素,最坏的情况就是O(n)。所以可以从两端进行查找,总的时间复杂度是O(nlogn)。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3
 4 const int maxn = 200000 + 10;
 5 int a[maxn], L[maxn], R[maxn];
 6
 7 map<int, int> cur;
 8
 9 inline bool ok(int pos, int l, int r)
10 { return L[pos] < l && R[pos] > r; }
11
12 bool solve(int l, int r)
13 {
14     if(l >= r) return true;
15     for(int i = 0; l+i <= r-i; i++)
16     {
17         if(ok(l+i, l, r)) return solve(l, l+i-1) && solve(l+i+1, r);
18         else if(ok(r-i, l, r)) return solve(l, r-i-1) && solve(r-i+1, r);
19     }
20     return false;
21 }
22
23 int main()
24 {
25     //freopen("in.txt", "r", stdin);
26
27     int T; scanf("%d", &T);
28     while(T--)
29     {
30         int n; scanf("%d", &n);
31         for(int i = 0; i < n; i++) scanf("%d", &a[i]);
32         cur.clear();
33         for(int i = 0; i < n; i++)
34         {
35             L[i] = cur.count(a[i]) ? cur[a[i]] : -1;
36             cur[a[i]] = i;
37         }
38         cur.clear();
39         for(int i = n-1; i >= 0; i--)
40         {
41             R[i] = cur.count(a[i]) ? cur[a[i]] : n;
42             cur[a[i]] = i;
43         }
44
45         printf("%s\n", solve(0, n-1) ? "non-boring" : "boring");
46     }
47
48     return 0;
49 }

代码君

时间: 2024-10-11 00:20:16

UVa 1608 (分治 中途相遇) Non-boring sequences的相关文章

UVA 1608 Non-boring sequences

#include<bits/stdc++.h> #define REP(i,a,b) for(int i=a;i<=b;i++) #define MS0(a) memset(a,0,sizeof(a)) using namespace std; typedef long long ll; const int maxn=200100; const int INF=1<<29; int n,a[maxn]; int L[maxn],R[maxn]; map<int,int&

uva 6757 Cup of Cowards(中途相遇法,貌似)

uva 6757 Cup of CowardsCup of Cowards (CoC) is a role playing game that has 5 di?erent characters (Mage, Tank, Fighter,Assassin and Marksman). A team consists of 5 players (one from each kind) and the goal is to kill amonster with L life points. The

UVA 1326 Jurassic Remains 中途相遇法

题目链接:点击打开链接 题意:给定n个字符串,选尽可能多的字符串使得每种字母出现的次数为偶数次 思路: 中途相遇法 import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.Comparator; import java.util.Iterator; import java.util.LinkedLi

uva 1608 不无聊的序列(附带常用算法设计和优化策略总结)

uva 1608 不无聊的序列(附带常用算法设计和优化策略总结) 紫书上有这样一道题: 如果一个序列的任意连续子序列中都至少有一个只出现一次的元素,则称这个序列时不无聊的.输入一个n个元素的序列,判断它是不是无聊的序列.n<=200000. 首先,在整个序列中找到只出现一次的元素ai.如果不能找到,那它就是无聊的.不然,就可以退出当前循环,递归判断[1, i-1]和[i+1, n]是不是无聊的序列.然而怎么找ai很重要.如果从一头开始找,那么最差情况下的时间复杂度就是O(n^2)的.而如果从两头

算法优化策略之“中途相遇”算法思想

中途相遇法,这是一种特殊的算法,大体思路是从两个不同的方向来解决问题,最终"汇集"到一起."双向广度优先搜索"算法就有一点中途相遇的味道.下面我们通过一道具体的题目,来了解一下这种算法思想的应用.和为0的4个值(4 Value Whose Sum is Zero,ACM/ICPC SWERC 2005,UVa 1152)给定4个n(1<=n<=400)元素集合A,B,C,D,要求分别从中选取一个元素a,b,c,d,使得a+b+c+d=0.问有多少种选法?

uva1152 - 4 Values whose Sum is 0(枚举,中途相遇法)

用中途相遇法的思想来解题.分别枚举两边,和直接暴力枚举四个数组比可以降低时间复杂度.可是我不会写...看了紫书作者刘汝佳老师的代码,真是太美了!简单明了,就像看吕钦下的棋一样.我就模仿的写了一下: #include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<map> #include<set>

POJ 1840 Eqs Hash + 中途相遇法

把等式分成两拨算用中途相遇法就好了. 不过要注意的是这里不能用map,会超时,要自己手写hash,我重载了[]操作符之后用起来和map差不多,很随意 #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #include <vector> #include <string> #include <qu

(中等) CF 585D Lizard Era: Beginning,中途相遇。

In the game Lizard Era: Beginning the protagonist will travel with three companions: Lynn, Meliana and Worrigan. Overall the game has nmandatory quests. To perform each of them, you need to take exactly two companions. The attitude of each of the com

Codeforces Round #297 (Div. 2) E题. Anya and Cubes (中途相遇法)

题目地址:Anya and Cubes 比赛的时候居然没想起中途相遇法...这题也是属于想起来就很简单系列. 中途相遇法也叫折半搜索.就是处理前一半,把结果储存起来,再处理后一半,然后匹配前一半存储的结果. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib