题解:P15849 三只迅猛龙,八叉线段树
记
则对于区间
题目中的条件为
这即是说,对于任意的两种不同颜色
展开这个东西后是
为了寻找满足条件的最长连续子区间,我们对于每一个
好的认真分析完了,下面开始搞笑。
我们考虑建一个动态开点的八叉线段树,修改/询问时将偏序的三个维度进行左右的递归。写法与普通单点修改、区间查询最小值的线段树比较类似,但是需要复制八份并进行边界判断。
时间复杂度应是
代码使用 AI 生成。
#include<iostream>
#include<cstring>
using namespace std;
const int N=2e5+5,M=5e6+5,INF=0x3f3f3f3f;
int ans,node,n,k,a[N],tr[M],son[M][8],s[N][3],v[N][3];
void change(int& x,int lf,int rf,int lg,int rg,int lh,int rh,int f,int g,int h,int o)
{
if(lf>rf || lg>rg || lh>rh)return;
if(!x){tr[x=++node]=INF;}
if(lf==rf && lg==rg && lh==rh){tr[x]=min(tr[x],o);return;}
int mf=lf+rf>>1,mg=lg+rg>>1,mh=lh+rh>>1;
if(f<=mf && g<=mg && h<=mh)change(son[x][0],lf,mf,lg,mg,lh,mh,f,g,h,o);
if(f<=mf && g<=mg && h>mh)change(son[x][1],lf,mf,lg,mg,mh+1,rh,f,g,h,o);
if(f<=mf && g>mg && h<=mh)change(son[x][2],lf,mf,mg+1,rg,lh,mh,f,g,h,o);
if(f<=mf && g>mg && h>mh)change(son[x][3],lf,mf,mg+1,rg,mh+1,rh,f,g,h,o);
if(f>mf && g<=mg && h<=mh)change(son[x][4],mf+1,rf,lg,mg,lh,mh,f,g,h,o);
if(f>mf && g<=mg && h>mh)change(son[x][5],mf+1,rf,lg,mg,mh+1,rh,f,g,h,o);
if(f>mf && g>mg && h<=mh)change(son[x][6],mf+1,rf,mg+1,rg,lh,mh,f,g,h,o);
if(f>mf && g>mg && h>mh)change(son[x][7],mf+1,rf,mg+1,rg,mh+1,rh,f,g,h,o);
tr[x]=INF;
for(int i=0;i<8;i++)
if(son[x][i])tr[x]=min(tr[x],tr[son[x][i]]);
}
int query(int x,int lf,int rf,int lg,int rg,int lh,int rh,int qlf,int qrf,int qlg,int qrg,int qlh,int qrh)
{
if(lf>rf || lg>rg || lh>rh || !x)return INF;
if(qlf<=lf && rf<=qrf && qlg<=lg && rg<=qrg && qlh<=lh && rh<=qrh)
return tr[x];
int mf=lf+rf>>1,mg=lg+rg>>1,mh=lh+rh>>1,ret=INF;
if(qlf<=mf && lf<=qrf && qlg<=mg && lg<=qrg && qlh<=mh && lh<=qrh)
ret=min(ret,query(son[x][0],lf,mf,lg,mg,lh,mh,qlf,qrf,qlg,qrg,qlh,qrh));
if(qlf<=mf && lf<=qrf && qlg<=mg && lg<=qrg && qlh<=rh && mh<qrh)
ret=min(ret,query(son[x][1],lf,mf,lg,mg,mh+1,rh,qlf,qrf,qlg,qrg,qlh,qrh));
if(qlf<=mf && lf<=qrf && qlg<=rg && mg<qrg && qlh<=mh && lh<=qrh)
ret=min(ret,query(son[x][2],lf,mf,mg+1,rg,lh,mh,qlf,qrf,qlg,qrg,qlh,qrh));
if(qlf<=mf && lf<=qrf && qlg<=rg && mg<qrg && qlh<=rh && mh<qrh)
ret=min(ret,query(son[x][3],lf,mf,mg+1,rg,mh+1,rh,qlf,qrf,qlg,qrg,qlh,qrh));
if(qlf<=rf && mf<qrf && qlg<=mg && lg<=qrg && qlh<=mh && lh<=qrh)
ret=min(ret,query(son[x][4],mf+1,rf,lg,mg,lh,mh,qlf,qrf,qlg,qrg,qlh,qrh));
if(qlf<=rf && mf<qrf && qlg<=mg && lg<=qrg && qlh<=rh && mh<qrh)
ret=min(ret,query(son[x][5],mf+1,rf,lg,mg,mh+1,rh,qlf,qrf,qlg,qrg,qlh,qrh));
if(qlf<=rf && mf<qrf && qlg<=rg && mg<qrg && qlh<=mh && lh<=qrh)
ret=min(ret,query(son[x][6],mf+1,rf,mg+1,rg,lh,mh,qlf,qrf,qlg,qrg,qlh,qrh));
if(qlf<=rf && mf<qrf && qlg<=rg && mg<qrg && qlh<=rh && mh<qrh)
ret=min(ret,query(son[x][7],mf+1,rf,mg+1,rg,mh+1,rh,qlf,qrf,qlg,qrg,qlh,qrh));
return ret;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n>>k;
for(int i=1;i<=n;i++)
cin>>a[i],a[i]--,s[i][a[i]]++;
int rt=0;change(rt,-N,N,-N,N,-N,N,0,0,0,0);
for(int i=1,v0,v1,v2;i<=n;i++)
{
for(int j=0;j<3;j++)s[i][j]+=s[i-1][j];
v0=s[i][0]-s[i][1],v1=s[i][1]-s[i][2],v2=s[i][0]-s[i][2];
int qry=query(rt,-N,N,-N,N,-N,N,-k+v0,k+v0,-k+v1,k+v1,-k+v2,k+v2);
ans=max(ans,i-qry);
change(rt,-N,N,-N,N,-N,N,v0,v1,v2,i);
}
cout<<ans;
}