【P1972】HH羅区ネックレス

タイトル

トピックリンク:https://www.luogu.com.cn/problem/P1972
で構成される美しい貝殻の様々なからHH文字列のネックレス。HHはので、すべての散歩の後、彼は、彼らが表現の意味を考えて、しばらくアウトシェルに無料になります、幸運をもたらすとは異なるシェルを信じています。HHは、常に新しいシェルを集めるので、彼は長いネックレスを取得しています。
シェルの一定期間、どのように多くの異なったシェルを含む:ある日、彼は突然問題を提起しますか?ネックレスは長すぎるので、この質問は......答えることは困難です。そこで彼は、この問題を解決するために、賢明なあなたを助けるために持っていました。

思考

チームを書き込む前のMoである\(O(N \ SQRT { N})\) アルゴリズムが。今データは、書き込みに戻ってくる、その後、強化してきた\(O(N \ Nログ )\) アルゴリズムを。
束のために考えてみましょう(= xは\ R_iと)\尋ねた(I \)\、我々が見つかりました。その内の数字は、以下の場合に\(\ [、X 1]は ) 何回か登場し、その後、より以上の最大値を取る(\ X \)デジタル位置が明確に最善です。
私たちは私たちが知っている限り、ポイントの束を依頼することと同じ権利を扱っているので、\([1、x]はを\ ) どこのことができます。各桁の最終的な位置に表示されます。
ツリーアレイ、プロセス確立\(X = I \)を、アレイツリー内の位置\(J \)は間隔を表し\([1、i]の\ ) 、位置(\ \ J)の上番号である場合(これは、最後の発生である\(C [I] \で\ {0,1 \} \) )。その後、クエリの時間\([L、X] \) 答えは\(\ SUM _ ^ {X} L {I} = C [I] \) フェンウィックツリー\(O(\ nはログ) \) を取得。
位置から\(I \)の位置の問い合わせに転送(I + 1 \)\問い合わせ時に、我々\([I + 1] \) アレイ上のツリーの最初の発生の位置がクリアされ、位置\(I + 1 \)は 1標識。それでも\(O(\ nはログ)
\) 時間複雑\(O(N \ Nログ )\)

コード

#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;

const int N=1000010;
int n,m,a[N],last[N],ans[N];

struct ASK
{
    int l,r,id;
}ask[N];

struct BIT
{
    int c[N];
    
    int ask(int x)
    {
        int sum=0;
        for (int i=x;i;i-=i&-i)
            sum+=c[i];
        return sum;
    }
    
    void add(int x,int val)
    {
        if (!x) return;
        for (int i=x;i<=n;i+=i&-i)
            c[i]+=val;
    }
}bit;

bool cmp(ASK x,ASK y)
{
    return x.r<y.r;
}

int read()
{
    int d=0,f=1; char ch=getchar();
    while (!isdigit(ch)) f=ch=='-'?-1:f,ch=getchar();
    while (isdigit(ch)) d=(d<<3)+(d<<1)+ch-48,ch=getchar();
    return d*f;
}

int main()
{
    n=read();
    for (int i=1;i<=n;i++)
        a[i]=read();
    m=read();
    for (int i=1;i<=m;i++)
        ask[i].l=read(),ask[i].r=read(),ask[i].id=i;
    sort(ask+1,ask+1+m,cmp);
    for (int i=1;i<=m;i++)
    {
        for (int j=ask[i-1].r+1;j<=ask[i].r;j++)
            bit.add(last[a[j]],-1),bit.add(j,1),last[a[j]]=j;
        ans[ask[i].id]=bit.ask(ask[i].r)-bit.ask(ask[i].l-1);
    }
    for (int i=1;i<=m;i++)
        printf("%d\n",ans[i]);
    return 0;
}

おすすめ

転載: www.cnblogs.com/stoorz/p/12207743.html
おすすめ