Luogu P6349 [[PA2011] Kangaroos]の問題を解決する

まず、質問の変換について考えます。2つの間隔が交差する可能性がある2つの間隔の共通部分を呼び出します。各クエリは、シーケンス内の最も長い連続一致の長さです。

セグメントシーケンスの\([L、R] \ ) セクション及び問い合わせ\([L、R&LT] \)、YESの場合\(L \ leqslant R \)\(L \ leqslant R&LT \) 次に、これらの2つの範囲を一致させることができます。

ドットを使用して間隔を表し、\(KD \ Tree \)を使用してすべてのクエリ間隔を維持できます。シーケンス間隔を使用して、各クエリの一致情報を1つずつ更新できます。

ため\(KD \ツリー\)青い長方形は、図の長方形等の矩形を維持すると考えられます。

ポイントが赤い四角形の上にある場合、そのポイントは四角形内のすべてのポイントと一致できます。四角形に追加マークを追加して、四角形内のすべてのポイントの現在の一致数を1つ増やします。

ポイントが黄色の四角形の上にある場合、そのポイントと四角形内のすべてのポイントは一致せず、四角形にクリアマークが付けられて、四角形内のすべてのポイントの現在の一致数がクリアされます。

同時に、プロセス全体におけるポイントの過去の最大一致数が記録されます。これは、最後のポイントに対応するクエリに対する回答です。

長方形が空になった後、一致数を増やすための一連の操作が行われますが、ここで追加マークを付けるのは間違いなので、割り当てマークを割り当て、追加すると割り当てマークが追加され、これによりステージは、マーカーの履歴最大値を割り当て、それを使用して、その時点での履歴の最大一致数を更新します。

多くのタグがあり、多くの詳細があります。特定の実装のコードを参照してください。

\(コード:\)

#include<bits/stdc++.h>
#define maxn 400010
using namespace std;
template<typename T> inline void read(T &x)
{
    x=0;char c=getchar();bool flag=false;
    while(!isdigit(c)){if(c=='-')flag=true;c=getchar();}
    while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    if(flag)x=-x;
}
int n,m,root,tot,type;
int cov[maxn],his[maxn],add[maxn],tag[maxn];
int ans[maxn],ma[maxn],cnt[maxn];
struct node
{
    int l,r;
}p[maxn];
struct KD_tree
{
    int d[2],mi[2],ma[2],ls,rs,id;
}t[maxn],dat[maxn];
bool cmp(const KD_tree &a,const KD_tree &b)
{
    return a.d[type]<b.d[type];
}
void pushup(int x)
{
    int ls=t[x].ls,rs=t[x].rs;
    for(int i=0;i<=1;++i)
    {
        t[x].ma[i]=t[x].mi[i]=t[x].d[i];
        if(ls)
        {
            t[x].ma[i]=max(t[x].ma[i],t[ls].ma[i]);
            t[x].mi[i]=min(t[x].mi[i],t[ls].mi[i]);
        }
        if(rs)
        {
            t[x].ma[i]=max(t[x].ma[i],t[rs].ma[i]);
            t[x].mi[i]=min(t[x].mi[i],t[rs].mi[i]);
        }
    }
}
void update(int x,int v)
{
    cnt[x]+=v,ma[x]=max(ma[x],cnt[x]);
}
void pushadd(int x,int v)
{
    update(x,v);
    if(cov[x]) tag[x]+=v,his[x]=max(his[x],tag[x]);
    else add[x]+=v;
}
void pushcov(int x)
{
    if(!cov[x]) cov[x]=1,his[x]=0;
    cnt[x]=tag[x]=0;
}
void pushtag(int x,int v1,int v2)
{
    cov[x]=1,his[x]=max(his[x],v2);
    cnt[x]=tag[x]=v1,ma[x]=max(ma[x],his[x]);
}
void pushdown(int x)
{
    int ls=t[x].ls,rs=t[x].rs;
    if(add[x])
    {
        pushadd(ls,add[x]),pushadd(rs,add[x]);
        add[x]=0;
    }
    if(cov[x])
    {
        pushtag(ls,tag[x],his[x]),pushtag(rs,tag[x],his[x]);
        cov[x]=tag[x]=0;
    }
}
void build(int l,int r,int k,int &x)
{
    x=++tot,type=k;
    int mid=(l+r)>>1;
    nth_element(dat+l+1,dat+mid+1,dat+r+1,cmp);
    t[x]=dat[mid];
    if(l<mid) build(l,mid-1,k^1,t[x].ls);
    if(r>mid) build(mid+1,r,k^1,t[x].rs);
    pushup(x);
}
bool in(KD_tree tr,int l,int r)
{
    return tr.ma[0]<=r&&l<=tr.mi[1];
}
bool out(KD_tree tr,int l,int r)
{
    return tr.mi[0]>r||l>tr.ma[1];
}
void modify(int x,int l,int r)
{
    int ls=t[x].ls,rs=t[x].rs;
    if(in(t[x],l,r))
    {
        pushadd(x,1);
        return;
    }
    if(out(t[x],l,r))
    {
        pushcov(x);
        return;
    }
    pushdown(x);
    if(t[x].d[0]<=r&&l<=t[x].d[1]) update(x,1);
    else cnt[x]=0;
    if(ls) modify(ls,l,r);
    if(rs) modify(rs,l,r);
}
void dfs(int x)
{
    int ls=t[x].ls,rs=t[x].rs;
    pushdown(x),ans[t[x].id]=ma[x];
    if(ls) dfs(ls);
    if(rs) dfs(rs);
}
int main()
{
    read(n),read(m);
    for(int i=1;i<=n;++i) read(p[i].l),read(p[i].r);
    for(int i=1;i<=m;++i)
        read(dat[i].d[0]),read(dat[i].d[1]),dat[i].id=i;
    build(1,m,0,root);
    for(int i=1;i<=n;++i) modify(root,p[i].l,p[i].r);
    dfs(root);
    for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
    return 0;
}

おすすめ

転載: www.cnblogs.com/lhm-/p/12683453.html