codeforces-1102e

http://www.javashuo.com/article/p-kydmcfvw-em.htmlhtml

这道题很锻炼思惟,,是到好题,,就是我不在状态,,没看出来线段间的关系,,学会了求一个区间里相同元素看做一个线段的总的线段的数量的方法,,用map保存最远的元素,遍历寻找判断就好了。。。ios

分析

题意是给你一个数组a,,让你构造一个数组b,,数组b知足的条件是:c++

  • \(b_1=0\)
  • 数组b是一个不降低的序列,,
  • 对于 \(a[i]=a[j]\) 的状况要使得 \(b[i]=b[j]\),,,

求b的可能的种类数git

一开始我把它当成纯数学题,,而后想要找出一个可能的公式,,最后状况太多,判断麻烦放弃了,,,github

官方的题解也没看进去,,,(主要是第一看到这个思路时没明白那个线段是干啥的,,)数组

后来看了这我的的思路,,post

大概思路以下:ui

由于最后的b是一个不降低序列,,因此当 \(a[i]=a[j]\) 时,,必然有 \(b[i]=b[i+1]=,,,,=b[j]\),,,spa

也就是说对于a中相等的两个元素对应的b之间都是一段相等的元素,,,code

经过这个思路,咱们能够求a中能够用两个相同的元素划分红多少个线段(有重叠的线段要合并为一个,,这一段的元素都相同)

为啥要求线段的数量 \(ans\) 呢,,由于b要知足的第三个条件中能够看出两个相邻的且 \(a[i] \ne a[j]\)\(b[i],b[j]\) 只有两种取值,,又由于线段内的取值相同,,因此b的状况就是 \(2^{ans-1}\)了,,,

eg:\(a={1,2,1,2,3}\) 中1对应的线段是{1,2,1}, 2对应的线段是 {2,1,2} 还有 {3},,由于有重叠,,合并后的就是{1,2,1,2},{3},,种类数就是 \(2^{2-1}\)

那么怎么求线段数呢,,

咱们能够先假设每一个数都自成一个线段,那么就一共有ans=n个,,而后对于每个大的线段的合并就是 \(ans-=(线段的左端点-线段的右端点)当a[i]=a[j]时,也就是ans-=(j-i)\)

左端点能够遍历整个数组,,右端点就用map保存每一个数最右的位置,,从左向右遍历一下就能够保证每一个数的最右边的位置,,,这样当咱们与当前遍历的点相同的点可能有一个右端点的时候,,说明如今遍历的位置和那个点之间能够构成一个线段,,减去中间的线段的数量就好了,,,

//cf
#include <bits/stdc++.h>
//#include <iostream>
//#include <cstdio>
//#include <cstdlib>
//#include <string.h>
//#include <algorithm>
#define aaa cout<<233<<endl;
#define endl '\n'
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
const int inf = 0x3f3f3f3f;//1061109567
const ll linf = 0x3f3f3f3f3f3f3f;
const double eps = 1e-6;
const double pi = 3.14159265358979;
const int maxn = 1e6 + 5;
const int maxm = 2e5 + 5;
const ll mod = 1e9 + 7;
int a[maxn];
inline ll _pow(ll a, ll b, ll p = 998244353)
{
    ll ret = 1;
    while(b)
    {
        if(b & 1)ret = (ret * a) % p;
        a = (a * a) % p;
        b >>= 1;
    }
    return ret;
}
int main()
{
//    freopen("233.in" , "r" , stdin);
//    freopen("233.out" , "w" , stdout);
    ios_base::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int n; cin >> n;
    map<int, int> mp;
    for(int i = 1; i <= n; ++i)cin >> a[i];
    for(int i = 1; i <= n; ++i)mp[a[i]] = i;
    int index = 1;
    int ans = n;
    for(int i = 1; i <= n; ++i)
    {
        index = max(index, i);
        if(mp[a[i]] > index)
        {
            ans -= (mp[a[i]] - index);
            index = mp[a[i]];
        }
    }
    cout << _pow(2, ans - 1) << endl;
    return 0;
}

溜了溜了,,贼困今天,,,感冒真不爽 (end)

本站公众号
   欢迎关注本站公众号,获取更多信息