几天之前写了个莫队+线段树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;
}