Bzoj4358 XSY1535 [] []配列permuモリブデン(Mo +チーム互いに素セット)

Moのチームを考えてみましょうが、我々はこのようなものが唯一サポートした\(イン\) 、(サポートは再訪する方法については)をサポートしていません\(デル\)の動作を、私たちはただの構築\(イン\)されていません(\デル\)のMoチーム。

我々ソートMoのチームの方法としては、最初のキーワード\(リットル\)ブロックが配置され、第二のキーである\(のR \) 注文を排出ときに、確か場合(Lの\)\ブロックが配置されていることは、同じである\(R&LT \)単調に増加するので、我々は(Lの\)を\問い合わせ同じブロックに処理すること。ブロックのために提供\(B \) その終了位置\(エンド\) 我々は最初の配列の全ての完全な分類を見つける\(Lの\)ブロックが配置されている(Bの\)\クエリを\ (Q_1 \)、\ (Q_2 \) ...... \(\ q_k) その後、お問い合わせは、アレイ内の連続していなければならない、と彼らの\(R \)確かに単調。

そして、これらは確かに、このように長いです尋ねます:

ここに画像を挿入説明

以来\(R \)単調に増加、その後のために\(R \)私たちに直接\(イン\)だけで罰金。以下のための\(リットル\) 起因する\(リットル\)ブロックで\(B \)ので、私たちのそれぞれから直接依頼する内部、\(エンド\)暴力の左に\(イン\)その上に。

\(イン\)の操作、我々は互いに素-設定、メンテナンスを考えます。各値が挿入のために\(X-は\) 我々は値フィールドでそれを見つけて別々に入れて、\(X-1 \)および(X + 1 \)\互いに素セットリンクに(そうでない場合は偽関節)、その答えは、すべての調査と最大に焦点を当てています\(サイズ\)

コードは以下の通りであります:

#include<bits/stdc++.h>

#define N 50010

using namespace std;

struct Question
{
    int l,r,block,id;
}q[N];

int n,m,len,block,a[N],ed[N],ans,Ans[N],st[N],top;
int fa1[N],size[N];
int fa2[N],minn[N],maxn[N];

int find1(int x)
{
    return fa1[x]==x?x:fa1[x]=find1(fa1[x]);
}

int find2(int x)
{
    return fa2[x]==x?x:fa2[x]=find2(fa2[x]);
}

int get(int x)
{
    return (x-1)/len+1;
}

bool operator < (Question a,Question b)
{
    return a.block==b.block?a.r<b.r:a.l<b.l;
}

void add1(int u)
{
    int v;
    fa1[u]=u,size[u]=1;
    if(v=find1(u-1))
        fa1[v]=u,size[u]+=size[v];
    if(v=find1(u+1))
        fa1[v]=u,size[u]+=size[v];
    ans=max(ans,size[u]);
}

void add2(int u,int &Ans)
{
    int v;
    st[++top]=u;
    fa2[u]=u,minn[u]=maxn[u]=u;
    if(v=find2(u-1))minn[u]=minn[v];
    else if(v=find1(u-1)) minn[u]-=size[v];
    if(v=find2(u+1))maxn[u]=maxn[v];
    else if(v=find1(u+1)) maxn[u]+=size[v];
    Ans=max(Ans,maxn[u]-minn[u]+1);
    if(minn[u]!=u)fa2[minn[u]]=u,st[++top]=minn[u];
    if(maxn[u]!=u)fa2[maxn[u]]=u,st[++top]=maxn[u];
}

int main()
{
    scanf("%d%d",&n,&m);
    block=len=sqrt(n);
    while(block*len<n)block++;
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    for(int i=1,edd=len;i<=block;i++,edd=min(edd+len,n))
        ed[i]=edd;
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&q[i].l,&q[i].r);
        q[i].block=get(q[i].l),q[i].id=i;
    }
    sort(q+1,q+m+1);
    for(int p=1,i=1;i<=m;i=p+1,p=i)
    {
        memset(fa1,0,sizeof(fa1));
        ans=0;
        while(q[i].block==q[p+1].block)p++;
        int now=ed[q[i].block];
        for(int j=i;j<=p;j++)
        {
            while(now<q[j].r)add1(a[++now]);
            Ans[q[j].id]=ans;
            for(int k=q[j].l;k<=min(q[j].r,ed[q[j].block]);k++)
                add2(a[k],Ans[q[j].id]);
            while(top)
                fa2[st[top--]]=0;
        }
    }
    for(int i=1;i<=m;i++)
        printf("%d\n",Ans[i]);
    return 0;
}

おすすめ

転載: www.cnblogs.com/ez-lcw/p/11617241.html