题意:给定一段数列,将其划分成最多的段 并且每段长度不超过 L且异或和不超过 X
有一个很显然的
O(N2)
的dp做法
dp[i]
表示到
i
为止最多能分成多少段
然后从前面最多
L
个 dp值转移出来
但是对前面
L
个 dp可以用 xor-trie维护一下
这样一来时间复杂度就是
O(Nlog(A))
每次将当前位置的前缀异或和插入trie,
并且在叶子节点维护一下当前位置的 dp值,其他节点维护出子树的 dp最大值
做到
i
的时候,在 trie树上沿着异或等于
X
的路径走
而小于
X
的路径可以直接用已经维护好的最大值
长度超过
L
的部分需要删掉,而 trie树不好直接删除,
所以只需将 dp值标记成 -1即可
由于 dp肯定是递增的,所以后来的值肯定更优,
所以前缀异或和相同的只需要保存最后一个即可
#include <vector>
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
#define MAX 100005
#define MAXN 1000005
#define maxnode 205
#define sigma_size 26
#define mem(x,v) memset(x,v,sizeof(x))
long long sum[MAX];
int ch[32*MAX][2];
int val[32*MAX];
int num[32*MAX];
int sz;
int dp[MAX];
int n,m,l;
void init(){
mem(ch[0],0);
sz=1;
}
void inser(int a,int id,int i,int u){
if(i==-1){
val[u]=dp[id];
//cout<<dp[id]<<" "<<id<<endl;
return;
}
int c=((a>>i)&1);
if(!ch[u][c]){
mem(ch[sz],0);
val[sz]=-1;
num[sz]=0;
ch[u][c]=sz++;
}
num[ch[u][c]]++;
inser(a,id,i-1,ch[u][c]);
val[u]=max(val[u],val[ch[u][c]]);
}
int query(int a,int x,int i,int u){
if(i==-1){
return val[u];
}
int c=((a>>i)&1);
int d=((x>>i)&1);
int ans=-1;
//if(c==1) cout<<i<<" "<<d<<endl;
if(d==1){
if(ch[u][c]&&num[ch[u][c]]) ans=max(ans,val[ch[u][c]]);
if(ch[u][c^1]&&num[ch[u][c^1]]) ans=max(ans,query(a,x,i-1,ch[u][c^1]));
}
else{
if(ch[u][c]&&num[ch[u][c]]) ans=max(ans,query(a,x,i-1,ch[u][c]));
}
//if(c==1) cout<<ans<<endl;
return ans;
}
void del(int a,int i,int u){
if(i==-1){
if(num[u]==0) val[u]=-1;
return;
}
int c=((a>>i)&1);
num[ch[u][c]]--;
del(a,i-1,ch[u][c]);
val[u]=val[ch[u][c]];
if(ch[u][c^1]&&num[ch[u][c^1]]) val[u]=max(val[u],val[ch[u][c^1]]);
}
int main()
{
int t;
cin>>t;
while(t--)
{
int n,x,l;
long long a,p,q;
sum[0]=0;
scanf("%d%d%d",&n,&x,&l);
cin>>a>>p>>q;
for(int i=1;i<=n;i++)
{
sum[i]=sum[i-1]^a;
a=(a*p+q)%268435456LL;
}
init();
mem(dp,0);
inser(0,0,30,0);
dp[0]=1;
for(int i=1;i<=n;i++)
{
if(i>l&&dp[i-l-1]) del(sum[i-l-1],30,0);
int cnt=query(sum[i],x,30,0);
if(cnt>=0)
{
dp[i]=cnt+1;
inser(sum[i],i,30,0);
}
}
printf("%d\n",dp[n]);
}
return 0;
}
因篇幅问题不能全部显示,请点此查看更多更全内容