dp[i]:前i个数最多分为几段(0为不可以分段)
dp[i]=max(dp[j])+1,(i-len<j<i&&xorsum[j+1,i]<=x)
朴素的转移复杂度为n^2
设pre[i]: 到第i位的异或前缀和,由于pre[i]^pre[j]=xorsum[j+1,i](j<i)
故建立01trie树维护可能转移过来的异或前缀和来优化,节点维护该分支下数的个数和所存的最大分段数,当插入两个相同的前缀和时,可知后插入的分段数肯定大于前插入的,所以直接覆盖即可
第一份为笔者勉强卡过去的代码,函数调用多.
第二份为标程,无函数递归调用,更为简洁快速.
View Code
1 #include <cstring> 2 #include <queue> 3 #include <map> 4 #include <set> 5 #include <cstdio> 6 #include <cstring> 7 #include <cmath> 8 #include <iostream> 9 #include <algorithm> 10 #include <vector> 11 #include <bitset> 12 #include <cstdlib> 13 #define lson rt[rr].l 14 #define rson rt[rr].r 15 using namespace std; 16 typedef unsigned long long ull; 17 typedef long long ll; 18 const int maxn=100100; 19 const int INF=0x3f3f3f3f; 20 const long long mod= 268435456; 21 const int depth=28; 22 int minf=INF; 23 struct node 24 { 25 int s,x,l,r; 26 }rt[3000000]; 27 int n,len,T,cnt=1; 28 long long a[maxn],p,q,x,pre[maxn]; 29 int dp[maxn]; 30 void pushup(int rr) 31 { 32 rt[rr].x=max(rt[lson].x,rt[rson].x); 33 } 34 void ins(long long z,int rr,int d,int num) 35 { 36 rt[rr].s++; 37 if(d==-1) 38 { 39 rt[rr].x=dp[num]; 40 return; 41 } 42 if(z&1<<d) 43 { 44 if(rson==0) 45 rson=++cnt; 46 ins(z,rson,d-1,num); 47 } 48 else 49 { 50 if(lson==0) 51 lson=++cnt; 52 ins(z,lson,d-1,num); 53 } 54 pushup(rr); 55 } 56 void del(long long z,int rr,int d,int num) 57 { 58 rt[rr].s--; 59 if(d!=-1) 60 { 61 if(z&1<<d) 62 del(z,rson,d-1,num); 63 else 64 del(z,lson,d-1,num); 65 pushup(rr); 66 } 67 if(rt[rr].s==0) 68 rt[rr].x=0; 69 } 70 int fnd(long long z,int d,int rr) 71 { 72 if(d==-1||rr==0) 73 return rt[rr].x; 74 if(x&1<<d) 75 { 76 if(z&1<<d) 77 return max(fnd(z,d-1,lson),rt[rson].x); 78 else 79 return max(fnd(z,d-1,rson),rt[lson].x); 80 } 81 else 82 { 83 if(z&1<<d) 84 return fnd(z,d-1,rson); 85 else 86 return fnd(z,d-1,lson); 87 } 88 } 89 int main() 90 { 91 // freopen("1002.in","r",stdin); 92 a[0]=0; 93 scanf("%d",&T); 94 while(T--) 95 { 96 cnt=1; 97 memset(rt,0,sizeof(rt)); 98 memset(dp,0,sizeof(dp)); 99 scanf("%d%lld%d",&n,&x,&len); 100 scanf("%lld%lld%lld",&a[1],&p,&q); 101 pre[1]=a[1]; 102 for(int i=2;i<=n;i++) 103 { 104 a[i]=(a[i-1]*p+q)%mod; 105 pre[i]=pre[i-1]^a[i]; 106 } 107 for(int i=1;i<=n;i++) 108 { 109 if(i>len) 110 del(pre[i-len-1],1,depth,i-len-1); 111 minf=INF; 112 int xx=fnd(pre[i],depth,1); 113 if(xx!=0) 114 dp[i]=xx+1; 115 else if(pre[i]<=x&&i<=len) 116 dp[i]=1; 117 ins(pre[i],1,depth,i); 118 } 119 printf("%d\n",dp[n]); 120 } 121 return 0; 122 }
1 #include <cstdio> 2 #include <vector> 3 using namespace std; 4 5 #define sz(x) (int)((x).size()) 6 7 typedef long long LL; 8 9 inline void chkmax(int &x, int y) { 10 if (x < y) x = y; 11 } 12 13 const int MAXN = 111111; 14 const int MAXM = 2800000; 15 16 int chd[MAXM][2], ptr[MAXM]; 17 vector<int> V[MAXM]; 18 19 int s[MAXN], a[MAXN], dp[MAXN]; 20 int m; 21 22 int add_node() { 23 chd[m][0] = chd[m][1] = -1; 24 ptr[m] = 0; 25 return m++; 26 } 27 28 void add(int x, int i) { 29 int u = 0; 30 for (int j = 27; j >= -1; j--) { 31 while (V[u].size() > ptr[u] && dp[V[u].back()] <= dp[i]) { 32 V[u].pop_back(); 33 } 34 V[u].push_back(i); 35 if (j < 0) { 36 return; 37 } 38 int c = x>>j&1; 39 if (!~chd[u][c]) { 40 chd[u][c] = add_node(); 41 } 42 u = chd[u][c]; 43 } 44 } 45 46 int get(int y, int x, int l) { 47 int u = 0, ret = 0; 48 for (int j = 27; j >= 0; j--) { 49 int a = x>>j&1, b = y>>j&1; 50 if (a) { 51 if (~chd[u][b]) { 52 int v = chd[u][b]; 53 for (int &k = ptr[v]; k < sz(V[v]) && V[v][k] < l; k++); 54 if (ptr[v] < sz(V[v])) { 55 chkmax(ret, 1+dp[V[v][ptr[v]]]); 56 } 57 } 58 } 59 u = chd[u][b^a]; 60 if (u == -1) { 61 return ret; 62 } 63 } 64 return ret; 65 } 66 67 int main() { 68 // freopen("data1.in", "r", stdin); 69 // freopen("data1.out", "w", stdout); 70 71 int ncase; 72 for (scanf("%d", &ncase); ncase--; ) { 73 int n, X, L, p, q; scanf("%d%d%d%d%d%d", &n, &X, &L, &a[1], &p, &q), X++; 74 for (int i = 2; i <= n; i++) { 75 a[i] = ((LL)a[i-1]*p+q) & 268435455; 76 } 77 for (int i = 1; i <= n; i++) { 78 s[i] = s[i-1] ^ a[i]; 79 } 80 m = dp[0] = 0; 81 add_node(); 82 add(0, 0); 83 for (int i = 1; i <= n; i++) { 84 dp[i] = get(s[i], X, i-L); 85 if (dp[i] > 0) { 86 add(s[i], i); 87 } 88 } 89 for (int i = 0; i < m; i++) { 90 V[i].clear(); 91 } 92 printf("%d\n", dp[n]); 93 } 94 return 0; 95 }