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)

本站公眾號
   歡迎關注本站公眾號,獲取更多信息