4358: permu|K-Dtree

几天之前写了个莫队+线段树T的飞起。。(据说卡常数可以卡过去。。
然后可以KD树做,标记比较难处理。
ymClairs的KD树神之标记http://www.cnblogs.com/clrs97/p/5049090.html

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#include<map>
#define L t[x].l
#define R t[x].r
#define ll long long
#define N 100005
using namespace std;
int sc()
{
    int i=0; char c=getchar();
    while(c>'9'||c<'0')c=getchar();
    while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
    return i;
} 
struct W{
    int D[2],mx[2],mn[2],p,l,r;
    int m,d,e,hm,hd,he;
}t[N];
int n,m,D,root,a[N],ans[N];
bool cmp(W a,W b){return a.D[D]<b.D[D];}
void push_up(int x)
{
    t[x].he=t[x].e=-1;
    for(int i=0;i<=1;i++)
    {
        t[x].mn[i]=min(t[x].D[i],min(t[L].mn[i],t[R].mn[i]));
        t[x].mx[i]=max(t[x].D[i],max(t[L].mx[i],t[R].mx[i]));
    }
}
void build(int &x,int l,int r,int dir)
{
    x=l+r>>1;D=dir;
    nth_element(t+l,t+x,t+r+1,cmp);
    if(l<x)build(L,l,x-1,dir^1);
    if(r>x)build(R,x+1,r,dir^1);
    push_up(x);
}
void hdoa(int x,int v)
{
    t[x].hm=max(t[x].hm,t[x].m+v);
    if(t[x].e>-1)
         t[x].he=max(t[x].he,t[x].e+v);
    else t[x].hd=max(t[x].hd,t[x].d+v);
}
void hdoc(int x,int v)
{
    t[x].hm=max(t[x].hm,v);
    t[x].he=max(t[x].he,v);
}
void doc(int x,int v)
{
    t[x].hm=max(t[x].hm,t[x].m=v);
    t[x].he=max(t[x].he,t[x].e=v);
    t[x].d=0;
}
void doa(int x,int v)
{
    t[x].hm=max(t[x].hm,t[x].m+=v);
    if(t[x].e>-1)
         t[x].he=max(t[x].he,t[x].e+=v);
    else t[x].hd=max(t[x].hd,t[x].d+=v);
}
void push_down(int x)
{
    if(t[x].hd)
    {
        if(L)hdoa(L,t[x].hd);
        if(R)hdoa(R,t[x].hd);
        t[x].hd=0;
    }
    if(t[x].he>-1)
    {
        if(L)hdoc(L,t[x].he);
        if(R)hdoc(R,t[x].he);
        t[x].he=-1;
    }
    if(t[x].d)
    {
        if(L)doa(L,t[x].d);
        if(R)doa(R,t[x].d);
        t[x].d=0;
    }else if(t[x].e>-1)
    {
        if(L)doc(L,t[x].e);
        if(R)doc(R,t[x].e);
        t[x].e=-1;
    }
}
void change(int x,int p)
{
    if(t[x].mn[0]>p||t[x].mx[1]<p){doc(x,0);return ;}
    if(t[x].mn[1]>=p&&t[x].mx[0]<=p){doa(x,1);return ;}
    push_down(x);
    if(t[x].D[0]<=p&&t[x].D[1]>=p)
        t[x].hm=max(t[x].hm,++t[x].m);
    else t[x].m=0;
    if(L)change(L,p);
    if(R)change(R,p);
}
void dfs(int x)
{
    if(!x)return ;
    push_down(x);
    ans[t[x].p]=t[x].hm;
    dfs(L);dfs(R);
}
int main()
{
    t[0].mx[0]=t[0].mx[1]=-1e9;
    t[0].mn[0]=t[0].mn[1]=1e9;
    n=sc();m=sc();
    for(int i=1;i<=n;i++)a[sc()]=i;
    for(int i=1;i<=m;i++)
        t[i].D[0]=sc(),t[i].D[1]=sc(),t[i].p=i;
    build(root,1,m,0);
    for(int i=1;i<=n;i++)
        change(root,a[i]);
    dfs(root);
    for(int i=1;i<=m;i++)printf("%d\n",ans[i]);
    return 0;
}

附上莫队+线段树代码(可以尝试一下卡常数。。说不定真能直接卡过去)

#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<vector>
#include<cstdio>
#include<queue>
#include<cmath>
#include<set>
#include<map>
#define N 200105
#define L x<<1
#define R x<<1|1
using namespace std;
int sc()
{
    int i=0,f=1;char c=getchar();
    while(c>'9'||c<'0'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
    return i*f;
}
struct T{int lmx,rmx,mx,v;}t[N*4];
struct W{int l,r,pos;}a[N];
int bl[N],ans[N],v[N];
int n,m,block,tot;
inline bool cmp1(W a,W b)
{
    return bl[a.l]<bl[b.l]||(bl[a.l]==bl[b.l]&&a.r<b.r);
}
inline void change(int x,int l,int r,int v,int f)
{
    if(l==r)
    {
        t[x].v+=f;
        t[x].mx=t[x].lmx=t[x].rmx=(bool)t[x].v;
        return;
    }
    int mid=l+r>>1;
    if(v<=mid)change(L,l,mid,v,f);else change(R,mid+1,r,v,f);
    t[x].lmx=t[L].lmx; t[x].rmx=t[R].rmx;
    if(t[L].lmx==mid-l+1)t[x].lmx+=t[R].lmx;
    if(t[R].rmx==r-mid)t[x].rmx+=t[L].rmx;
    t[x].mx=max(t[L].rmx+t[R].lmx,max(t[L].mx,t[R].mx));
}
int main()
{
    n=sc(),m=sc();block=sqrt(n);
    for(int i=1;i<=n;i++)
    {
        bl[i]=(i-1)/block+1;
        v[i]=sc();
    }
    for(int i=1;i<=m;i++)
        a[i].l=sc(),a[i].r=sc(),a[i].pos=i;
    sort(a+1,a+m+1,cmp1);
    int l=a[1].l,r=a[1].l-1;
    for(int i=1;i<=m;i++)
    {
        while(l<a[i].l)change(1,1,n,v[l++],-1);
        while(l>a[i].l)change(1,1,n,v[--l],1);
        while(r>a[i].r)change(1,1,n,v[r--],-1);
        while(r<a[i].r)change(1,1,n,v[++r],1);
        ans[a[i].pos]=t[1].mx;
    }
    for(int i=1;i<=m;i++)
        printf("%d\n",ans[i]);
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值