【HDU - 5845】Best Division(xor-trie、01字典树、dp)
2017-07-03 17:38
393 查看
BUPT2017 wintertraining(15) #7E
且A是这样给你的:A[1], P, Q。A[i]=(A[i-1]*P+Q)%M。M为\(2^{28}\)。
dp[i]=max(dp[j]+1),i-L<j<i,且s[j]^s[i]\(\le\) x。
dp
就是答案。
但是这样是\(O(n^2)\)。
用 异或字典树 优化为\(O(nlogA)\)。
字典树来维护s[i],总共N个数,最多28位,所以28*N个节点。
要找 j 满足s[j]异或s[i]不超过x的最大的dp[j]+1。我们沿着字典树一位位找,如果x这一位是0,那么s[j]这一位肯定是和s[i]相同,异或起来才不超过x。如果x这一位是1,那么s[j]这一位可以和s[i]相同,直接取这个节点的最大值;也可以是与s[i]不同,然后继续走。
因为长度不超过L,所以每次处理到第i个,要删去第i-L-1个。
因为一个异或值可能出现多次,所以记录出现次数,删去时减少一次出现次数,次数为0时将对应的值设为-1。
题意
把数组A划分为k个区间,每个区间不超过L长度,每一个区间异或和之和为S。现在求:S不超过X,区间个数的最大值。且A是这样给你的:A[1], P, Q。A[i]=(A[i-1]*P+Q)%M。M为\(2^{28}\)。
题解
容易想到dp, dp[i] :前 i 个数最多划分多少个区间。s[i]为前缀异或和。dp[i]=max(dp[j]+1),i-L<j<i,且s[j]^s[i]\(\le\) x。
dp
就是答案。
但是这样是\(O(n^2)\)。
用 异或字典树 优化为\(O(nlogA)\)。
字典树来维护s[i],总共N个数,最多28位,所以28*N个节点。
要找 j 满足s[j]异或s[i]不超过x的最大的dp[j]+1。我们沿着字典树一位位找,如果x这一位是0,那么s[j]这一位肯定是和s[i]相同,异或起来才不超过x。如果x这一位是1,那么s[j]这一位可以和s[i]相同,直接取这个节点的最大值;也可以是与s[i]不同,然后继续走。
因为长度不超过L,所以每次处理到第i个,要删去第i-L-1个。
因为一个异或值可能出现多次,所以记录出现次数,删去时减少一次出现次数,次数为0时将对应的值设为-1。
代码
#include <cstdio> #include <algorithm> #include <cstring> #define M 268435456 #define N 100005 using namespace std; int dp , a ; struct Trie{ int ch[N*28][2]; int val[N*28];//异或到当前位置不超过x的最多区间数 int cnt[N*28];//出现次数 int size; void init(){ size=0; memset(ch,0,sizeof ch); } void Insert(int node, int pos, int id, int num){ cnt[node]++; if(pos<0){ val[node]=dp[id]; return; } int bit=(num>>pos)&1; if(ch[node][bit]==0){ ch[node][bit]=++size; val[size]=-1; cnt[size]=0; } Insert(ch[node][bit], pos-1, id, num); val[node]=max(val[node], val[ch[node][bit]]); } int Query(int node, int pos, int x, int num){ if(pos<0) return val[node]; int xbit=(x>>pos)&1, nbit=(num>>pos)&1; int ans=-1; if(xbit){ if(ch[node][nbit]) ans = val[ch[node][nbit]]; if(ch[node][!nbit]) ans = max(ans, Query(ch[node][!nbit], pos-1, x, num)); } else if(ch[node][nbit]) ans = Query(ch[node][nbit], pos-1, x, num); return ans; } void Delete(int node, int pos, int num){ if(!--cnt[node]) val[node]=-1; if(pos<0) return; int bit=(num>>pos)&1; Delete(ch[node][bit], pos-1, num); val[node]=val[ch[node][bit]]; if(ch[node][!bit]) val[node]=max(val[node],val[ch[node][!bit]]); } }trie; int main(){ int t; scanf("%d", &t); while(t--){ int n,x,l; scanf("%d%d%d", &n,&x,&l); int p,q; scanf("%d%d%d", &a[1],&p,&q); for(int i=2;i<=n;++i) a[i]=(a[i-1]*p+q)%M; for(int i=2;i<=n;++i)a[i]^=a[i-1]; trie.init();trie.Insert(0,27,0,0); for(int i=1;i<=n;++i){ if(i>l+1&&dp[i-l-1]!=-1)trie.Delete(0, 27, a[i-l-1]); dp[i]=trie.Query(0, 27, x, a[i]); if(dp[i]!=-1){ dp[i]++; trie.Insert(0, 27, i, a[i]); } } printf("%d\n", dp ==-1?0:dp ); } return 0; }
相关文章推荐
- [HDU 5845] Best Division (xor-trie+dp)
- hdu 5845:Best Division(01字典树+dp)
- hdu 5845 Best Division(trie+dp,好题)
- Hdu-5845 Best Division (trie+DP)
- HDU 4825 Xor Sum (01字典树)
- HDU 4825:Xor Sum(01字典树+贪心)
- [HDU 4825] Xor Sum(01字典树+贪心)
- HDU 4825 Xor Sum (01字典树)
- HDU 4825 Xor Sum(01字典树)
- HDU 4825 Xor Sum(01字典树入门题)
- HDU-4825 Xor Sum (Trie 字典树 2014年百度之星程序设计大赛-资格赛)
- HDU 5269 ZYB loves Xor I [01字典树]【思维】
- hdu 4825 Xor Sum(01字典树求最大异或值)
- HDU 4825 Xor Sum(01字典树)
- hdu5845 Best Division (xor-trie+dp)
- Xor Sum HDU - 4825 01字典树入门题
- HDU 5269 ZYB loves Xor I 01trie
- [HDU 4825] Xor Sum(01字典树+贪心)
- hdu 4825 Xor Sum(01字典树)
- HDU - 6191 Query on A Tree 可持久化字典树(01Trie) || 字典树启发式合并