2016 Multi-University Training Contest 9--HDU5845--Best Division

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树维护可能转移过来的异或前缀和来优化,节点维护该分支下数的个数和所存的最大分段数,当插入两个相同的前缀和时,可知后插入的分段数肯定大于前插入的,所以直接覆盖即可
第一份为笔者勉强卡过去的代码,函数调用多.
第二份为标程,无函数递归调用,更为简洁快速.
  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 }
View Code
 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 }
View Code

转载于:https://www.cnblogs.com/lanvent/p/5780478.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值