HDU5845 trie tree optimization dp
Keywords:
PHP
http://acm.hdu.edu.cn/showproblem.php?pid=5845
Topic: Given a sequence, ask how many segments it can be divided into so that each sequence does not exceed L and XOR or X.
For interval XOR sum, it is easy to think of prefix XOR and de-optimization so that it can find interval XOR sum in O(1) time, and then we can write a n violence
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <bitset>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x)
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x)
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const double PI = acos(-1.0);
const double eps = 1e-9;
const int maxn = 1e5 + 10;
const int INF = 0x3f3f3f3f;
const int mod = 268435456;
LL N,X,L,P,Q;
LL a[maxn],dp[maxn];
LL pre[maxn];
LL sum(int i,int j){
return pre[j] ^ pre[i - 1];
}
int main(){
int T; Sca(T);
while(T--){
scanf("%lld%lld%lld",&N,&X,&L);
scanf("%lld%lld%lld",&a[1],&P,&Q);
for(int i = 2; i <= N ; i ++){
a[i] = ((a[i - 1] * P) + Q) % mod;
}
pre[0] = 0;
for(int i = 1; i <= N ; i ++) pre[i] = pre[i - 1] ^ a[i];
for(int i = 0; i <= N ; i ++) dp[i] = 0;
for(int i = 1; i <= N; i ++){
for(int j = max(0LL,i - L); j < i ; j ++){
if(sum(j + 1,i) <= X) dp[i] = max(dp[i],dp[j] + 1);
}
}
Prl(dp[N]);
}
return 0;
}
n Violence
We can find that for the same subscript as prep, the size of DP is monotonic, i. e. I > J and pre[i] = pre[j] then dp[i] > dp[j]. Since the exclusive sum between I and j is 0, it is clear that dp[i] - dp[j] >= 1
So for the interval of the preceding length L, we can consider using dictionary tree optimization, using 01 dictionary tree to maintain the maximum dp of each prefix and sum. Because monotonicity is satisfied, we only need to maintain the number of occurrences of each node for the deletion of dictionary tree, as long as the current node (occurrence number is not zero) still exists in the dictionary tree.This means that the current maximum value does not change (the greater the maximum value always follows)
If the current bit X is 0, it means that the pre current bit of the query is also 0, and the path of the current bit is the same as that of him. If X is 1, then the opposite path can be taken to make the bit as 1 as X, or the same path can be taken to make the bit zero, if it is 0,Then you don't have to go down to get the maximum value of the subtree directly, because the following must be smaller than X anyway
#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <bitset>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x)
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x)
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = 0,f = 1;char c = getchar();while (c<'0' || c>'9'){if (c == '-') f = -1;c = getchar();}
while (c >= '0'&&c <= '9'){x = x * 10 + c - '0';c = getchar();}return x*f;}
const int maxn = 1e5 + 10;
const int maxm = 5e6 + 10;
const LL INF = 1e18;
const LL mod = 268435456;
LL N,X,L,P,Q;
LL a[maxn],dp[maxn],pre[maxn];
int nxt[maxm][2],cnt,num[maxm];
LL val[maxm];
void insert(int j){
LL x = pre[j],v = dp[j];
int p = 1;
for(int i = 32; i >= 0; i --){
int id = (x >> i) & 1;
if(!nxt[p][id]){
nxt[p][id] = ++cnt;
val[cnt] = -INF; num[cnt] = nxt[cnt][0] = nxt[cnt][1] = 0;
}
p = nxt[p][id];
val[p] = max(val[p],v); num[p]++;
}
}
void del(int p,int i,LL x){
if(i == -1){if(!num[p]) val[p] = -INF;return;}
int id = (x >> i) & 1;
num[nxt[p][id]]--;
del(nxt[p][id],i - 1,x);
val[p] = val[nxt[p][id]];
if(nxt[p][id ^ 1] && num[nxt[p][id ^ 1]] > 0) val[p] = max(val[nxt[p][0]],val[nxt[p][1]]);
}
LL query(LL x){
int p = 1;
LL ans = -INF;
for(int i = 32; i >= 0 ; i --){
int id = (x >> i) & 1;
if((X >> i) & 1){
if(nxt[p][id] && num[nxt[p][id]]){
ans = max(ans,val[nxt[p][id]]);
}
if(nxt[p][id ^ 1] && num[nxt[p][id ^ 1]]){
p = nxt[p][id ^ 1];
}
}else{
if(!nxt[p][id] || !num[nxt[p][id]]) return ans;
p = nxt[p][id];
}
}
ans = max(ans,val[p]);
return ans;
return val[p];
}
int main(){
int T; Sca(T); cnt = 1;
while(T--){
for(int i = 0 ; i <= cnt; i ++){val[i] = -INF; nxt[i][0] = nxt[i][1] = num[i] = 0;}
scanf("%lld%lld%lld",&N,&X,&L); cnt = 1;
scanf("%lld%lld%lld",&a[1],&P,&Q);
for(int i = 2; i <= N ; i ++) a[i] = ((a[i - 1] * P) + Q) % mod;
pre[0] = dp[0] = 0; insert(0);
for(int i = 1; i <= N ; i ++) pre[i] = pre[i - 1] ^ a[i];
// For(i,1,N) cout << pre[i] << " ";
// cout << endl;
for(int i = 1; i <= N; i ++){
if(i - L - 1 >= 0 && dp[i - L - 1] >= 0) del(1,32,pre[i - L - 1]);
dp[i] = query(pre[i]) + 1;
if(dp[i] > 0) insert(i);
}
if(dp[N] < 0) dp[N] = 0;
Prl(dp[N]);
}
return 0;
}