C. Pearls in a Row

 

C. Pearls in a Row

题目大意:有n颗珍珠排成一排,每颗珍珠有一个类型ai,如果每一段中至少存在一个类型出现次数不少于2次,则这一段被称为good segment;求这排珍珠最多有多少个good segment。

思路:贪心。从头到尾遍历找good segment,只要找到符合条件的(最低条件,即某个数出现两次)记录,难点是最后一段的处理,如果恰好有剩余,加到前一段之中。寻找good segmen可以用set;

总结一下set的基本用法:

set集合容器:实现了红黑树的平衡二叉检索树的数据结构,插入元素时,它会自动调整二叉树的排列,把元素放到适当的位置,以保证每个子树根节点键值大于左子树所有节点的键值,小于右子树所有节点的键值;另外,还得保证根节点左子树的高度与右子树高度相等。
平衡二叉检索树使用中序遍历算法,检索效率高于vector、deque和list等容器,另外使用中序遍历可将键值按照从小到大遍历出来。
构造set集合主要目的是为了快速检索,不可直接去修改键值。

常用操作:

定义:例如:int型      set<int>S;(下面均已此为例,其他类型相似);
1.元素插入:insert() S.insert();
2.中序遍历:类似vector遍历(用迭代器) set<int>::itertator it(定义迭代器it)
3.反向遍历:利用反向迭代器reverse_iterator。
    例:
    set<int> s;
    ......
    set<int>::reverse_iterator rit;
    for(rit=s.rbegin();rit!=s.rend();rit++)
4.元素删除:与插入一样,可以高效的删除,并自动调整使红黑树平衡。
            set<int> s;
            s.erase(2);        //删除键值为2的元素
            s.clear();
5.元素检索:find(),若找到,返回该键值迭代器的位置,否则,返回最后一个元素后面一个位置。
            set<int> s;
            set<int>::iterator it;
            it=s.find(5);    //查找键值为5的元素
            if(it!=s.end())    //找到
                cout<<*it<<endl;
            else            //未找到
                cout<<"未找到";
6.自定义比较函数
    (1)元素不是结构体:
        例:
        //自定义比较函数myComp,重载“()”操作符
        struct myComp
        {
            bool operator()(const your_type &a,const your_type &b)
            [
                return a.data-b.data>0;
            }
        }
        set<int,myComp>s;
        ......
        set<int,myComp>::iterator it;
    (2)如果元素是结构体,可以直接将比较函数写在结构体内。
        例:
        struct Info
        {
            string name;
            float score;
            //重载“<”操作符,自定义排序规则
            bool operator < (const Info &a) const
            {
                //按score从大到小排列
                return a.score<score;
            }
        }
        set<Info> s;
        ......
        set<Info>::iterator it;

There are n pearls in a row. Let's enumerate them with integers from 1 to n from the left to the right. The pearl number i has the type ai.

Let's call a sequence of consecutive pearls a segment. Let's call a segment good if it contains two pearls of the same type.

Split the row of the pearls to the maximal number of good segments. Note that each pearl should appear in exactly one segment of the partition.

As input/output can reach huge size it is recommended to use fast input/output methods: for example, prefer to use scanf/printf instead of cin/cout in C++, prefer to use BufferedReader/PrintWriter instead of Scanner/System.out in Java.

Input

The first line contains integer n (1 ≤ n ≤ 3·105) — the number of pearls in a row.

The second line contains n integers ai (1 ≤ ai ≤ 109) – the type of the i-th pearl.

Output

On the first line print integer k — the maximal number of segments in a partition of the row.

Each of the next k lines should contain two integers lj, rj (1 ≤ lj ≤ rj ≤ n) — the number of the leftmost and the rightmost pearls in the j-th segment.

Note you should print the correct partition of the row of the pearls, so each pearl should be in exactly one segment and all segments should contain two pearls of the same type.

If there are several optimal solutions print any of them. You can print the segments in any order.

If there are no correct partitions of the row print the number "-1".

Sample test(s)

Input

5
1 2 3 4 1

Output

1
1 5

Input

5
1 2 3 4 5

Output

-1

Input

7
1 2 1 3 1 2 1

Output

2
1 3
4 7

 

#include <iostream>
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+5;
struct node
{
    int l,r;
}que[N];
int main()
{
   int n,k,x;

     while(~scanf("%d",&n))
     {
          k=0;

        int i=1;
        set<int>Q;
        set<int>::iterator it;

        while(i<=n)
         {
            que[k].l=i;
            while(i<=n)
            {
                scanf("%d",&x);
                i++;
                it=Q.find(x);
                if(it!=Q.end())
                {
                     Q.clear();
                que[k++].r=i-1;
                    break;
                }
                else
                {
                    Q.insert(x);
                }

            }
         }
         if(k==0)
            printf("-1\n");
         else
            {
                printf("%d\n",k);
                for(int i=0;i<k-1;i++)
                {
                    printf("%d %d\n",que[i].l,que[i].r);
                }
                printf("%d %d\n",que[k-1].l,n);
            }
     }
    return 0;
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值