「2017 山东二轮集训 Day1」第一题
题目描述
小火车沉迷垃圾手游不能自拔,正在玩碧蓝航线,可惜小火车的舰(lao)队(po)练度太低打不过副本,所以他只好去刷其余的副本来升级。
总共有 $ n $ 个副本编号从 $ 1 $ 到 $ n $,每个副本有个难度值 $ a_i $,小火车每天按照顺序刷连续的一段副本,第 $ j $ 天会刷的副本必须落在 $ l $ 到 $ r $ 之间。但是他是个很懒的人,每天一开始他的懒惰值为 $ 0 $,当他刷完一个副本以后懒惰值就会异或上 $ a_i $,小火车希望懒惰值一直保持单调不下降,请问每天他都有多少种刷副本的方法?
输入格式
第一行一个整数 $ n $,表示副本数量。
接下来一行 $ n $ 个整数表示副本的难度。
接下来一行一个整数 $ m $ 表示天数。
接下来 $ m $ 行每行两个整数 $ a, b $ 表示一组询问,为了体现程序的在线性,题目中说的 $ l $ 和 $ r $ 都需要计算得到,设上个询问的答案为 $ \text{lastAns} $(初始为 $ 0 $),则 $ l = (( a + \text{lastAns}) \bmod n) + 1, r = ((b + \text{lastAns}) \bmod n) + 1 $,当然如果这样求得的 $ l $ 和 $ r $ 满足 $ l > r $ 请将 $ l $ 和 $ r $ 交换。
输出格式
$ m $ 行每行一个整数表示答案。
数据范围与提示
对于 $ 20\ %$ 的数据 $ n, m \leq 5000 $,数据随机;
对于另外 $ 20\% $ 的数据 $ m = 1, l = 0, r = n - 1 $;
对于另外 $ 30\% $ 的数据随机;
对于 $ 100\% $ 的数据 $ n, m \leq 100000, 0 \leq a_i \leq 10 ^ 9 $。
显然从某天开始的刷副本方案的右端点构成一段连续区间。只要对于每个位置都求出它对应的区间的右端点就可以统计答案了。这里统计答案采用主席树,第$i$棵树维护的是$[1,i]$天对应的区间。由于是要支持区间修改的主席树,注意下放标记时新建节点这样的细节。
暴力找右端点,然后这道题就做完了。我的暴力跑得比下面的方法还快= =
容易想到对于每个位置二分答案求右端点。
考虑对于懒惰值$x$,怎样的$a_i$会使得它降。显然只讨论$a_i$非$0$的情况,写出下面的表:
$x$ | $0$ | $1$ | $0$ | $1$ |
---|---|---|---|---|
$a_i$ | $0$ | $0$ | $1$ | $1$ |
$ret$ | $0$ | $1$ | $1$ | $0$ |
发现$a_i$为$0$的位不会影响答案的合法性。容易发现从高位到低位讨论后,记$a_i$的最高位为第$k$位,那么不降当且仅当$x$的第$k$位是$0$。
所以用$cnt[i][j][0/1]$记录$a_1,a_2,..,a_i$的$i$个异或前缀和中,$j$作为$a$的最高位时最高位的$0/1$总个数。二分答案检查时每一位都验证一下就行了。
时间复杂度$O(nlognloga+mlogn)$。
1 |
|