Luogu6349 [PA2011]Kangaroos

Luogu6349 [PA2011]Kangaroos

\(\rm KDT\),历史最值

区间\([l_1,r_1]\)和区间\([l_2,r_2]\)相交,当且仅当\(l_1 \le r_2 \operatorname{and} l_2 \le r_1\),这就把题目转化为了一个二维平面上的修改和询问的问题。

考虑把询问序列当成二维平面上的点,依次加入序列\(a\),实时维护当前的答案。也就是,对满足条件的,对应点的值\(+1\),其他位置的值清\(0\),然后维护历史最大值即为答案。

然后,……,这个维护就离谱!\(WA\)了半天才通过。

如果不管历史最值,那么显然是维护加法标记和清空标记,钦定先清空后添加。

维护历史最值类似线段树维护,注意一种情况,就是在一个节点先清空,再加,再清空,实际上相当于一个值在这个节点短暂停留,还没有下放就消失了,我们不能忽略这一部分的贡献,可以维护一个标记永久化,最终处理时整棵子树答案与之取\(\max\)。同时也要注意清空时,加法标记和历史最大加法标记的下放。具体细节详见代码。

\(Code:\)

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<assert.h>
#define N 50005
#define M 200005
using namespace std;
const int INF=1000000007;
int n,m,mxp,ans[M];
struct Point
{
    int x,y,id;
    Point () {}
    Point (int xx,int yy,int zz):x(xx),y(yy),id(zz) {}
    void read(int I)
    {
        scanf("%d%d",&x,&y);
        id=I;
    }
}a[N],b[M];
struct node
{
    int xl,xr,yl,yr;
    int s,mxs,atag,mxatag,mxas;
    bool ctag;
}tr[M << 2];
struct range_query
{
    int xl,xr,yl,yr;
}kz;
bool cmpX(const Point &A,const Point &B)
{
    return A.x<B.x;
}
bool cmpY(const Point &A,const Point &B)
{
    return A.y<B.y;
}
void build(int p,int l,int r,bool opt)
{
    mxp=max(mxp,p);
    if (l==r)
    {
        tr[p].xl=tr[p].xr=b[l].x;
        tr[p].yl=tr[p].yr=b[l].y;
        return;
    }
    int mid(l+r >> 1);
    nth_element(b+l,b+mid,b+r+1,(!opt)?cmpX:cmpY);
    build(p << 1,l,mid,!opt),build(p << 1 | 1,mid+1,r,!opt);
    tr[p].xl=min(tr[p << 1].xl,tr[p << 1 | 1].xl);
    tr[p].xr=max(tr[p << 1].xr,tr[p << 1 | 1].xr);
    tr[p].yl=min(tr[p << 1].yl,tr[p << 1 | 1].yl);
    tr[p].yr=max(tr[p << 1].yr,tr[p << 1 | 1].yr);
}
void push_tag(int p,int tag1,int tag2)
{
    if (p>mxp)
        return;
    assert(tag1<=tag2);
    tr[p].mxs=max(tr[p].mxs,tr[p].s+tag2);
    tr[p].mxatag=max(tr[p].mxatag,tr[p].atag+tag2);
    tr[p].s+=tag1,tr[p].atag+=tag1;
}
void push_clean(int p)
{
    if (p>mxp)
        return;
    if (tr[p].ctag)
    {
        tr[p].mxas=max(tr[p].mxas,tr[p].mxatag);
        tr[p].atag=tr[p].mxatag=tr[p].s=0;
        tr[p].ctag=true;
        return;
    }
    if ((p << 1)<=mxp && tr[p << 1].ctag)
        tr[p << 1].mxatag=max(tr[p << 1].mxatag,tr[p << 1].atag+tr[p].mxatag),tr[p << 1].mxas=max(tr[p << 1].mxas,tr[p << 1].mxatag),tr[p << 1].atag=tr[p << 1].mxatag=0; else
        push_tag(p << 1,tr[p].atag,tr[p].mxatag);
    if ((p << 1 | 1)<=mxp && tr[p << 1 | 1].ctag)
        tr[p << 1 | 1].mxatag=max(tr[p << 1 | 1].mxatag,tr[p << 1 | 1].atag+tr[p].mxatag),tr[p << 1 | 1].mxas=max(tr[p << 1 | 1].mxas,tr[p << 1 | 1].mxatag),tr[p << 1 | 1].atag=tr[p << 1 | 1].mxatag=0; else
        push_tag(p << 1 | 1,tr[p].atag,tr[p].mxatag);
    tr[p].atag=tr[p].mxatag=tr[p].s=0;
    tr[p].ctag=true;
}
void push_down(int p)
{
    if (tr[p].ctag)
    {
        push_clean(p << 1);
        push_clean(p << 1 | 1);
    }
    push_tag(p << 1,tr[p].atag,tr[p].mxatag);
    push_tag(p << 1 | 1,tr[p].atag,tr[p].mxatag);
    tr[p].atag=tr[p].mxatag=0;
    tr[p].ctag=false;
}
void calc(int p)
{
    push_down(p);
    if (tr[p].xl>kz.xr || tr[p].xr<kz.xl || tr[p].yl>kz.yr || tr[p].yr<kz.yl)
    {
        push_clean(p);
        return;
    }
    if (kz.xl<=tr[p].xl && tr[p].xr<=kz.xr && kz.yl<=tr[p].yl && tr[p].yr<=kz.yr)
    {
        push_tag(p,1,1);
        return;
    }
    calc(p << 1),calc(p << 1 | 1);
}
void calc_all(int p,int l,int r)
{
    push_down(p);
    if (l==r)
    {
        ans[b[l].id]=max(tr[p].mxs,tr[p].mxas);
        return;
    }
    int mid(l+r >> 1);
    tr[p << 1].mxas=max(tr[p << 1].mxas,tr[p].mxas),tr[p << 1 | 1].mxas=max(tr[p << 1 | 1].mxas,tr[p].mxas);
    calc_all(p << 1,l,mid),calc_all(p << 1 | 1,mid+1,r);
}
int main()
{
    scanf("%d%d",&n,&m);
    for (int i=1;i<=n;++i)
        a[i].read(i);
    for (int i=1;i<=m;++i)
        b[i].read(i);
    build(1,1,m,0);
    for (int i=1;i<=n;++i)
    {
        kz.xl=1,kz.xr=a[i].y;
        kz.yl=a[i].x,kz.yr=INF;
        calc(1);
    }
    calc_all(1,1,m);
    for (int i=1;i<=m;++i)
        printf("%d\n",ans[i]);
    return 0;
}
posted @ 2021-04-13 20:33  GK0328  阅读(48)  评论(0编辑  收藏  举报