[SOJ475]【SPC #2】美丽的序列 ~ Beautiful Sequence【莫队】【哈希】

题意简述:给一个长度为\(n\)的序列,每次给出\(x, y\),求有多少区间\([l, r]\)满足\(x\leq l\leq r\leq y\),且\([l, r]\)中每个元素都出现了偶数次。\(1\leq n, q \leq 10^5, 1\leq a_i\leq 10^6\)。



设\(s_{i, j}\in[0, 1]\)表示前\(i\)个位置中,元素\(j\)出现的总次数\(\bmod 2\)的结果。显然\([l, r]\)中每个元素都出现了偶数次等价于\(\forall i\in [1, \max a] s_{l-1, i}=s_{r, i}\)。因此对每个\(s_{i}\)进行哈希,原问题就变成了区间元素出现个数平方和,也就是一道莫队入门题。

#include <bits/stdc++.h>
#define R register
#define ll long long
#define mp make_pair
#define pll pair<ll, ll>
using namespace std;
const int N = 110000, M = 1100000;
const ll mod[2] = {1e9 + 7, 1e9 + 9}, base[2] = {19260817, 19660813};

int n, q, B, bel[N], a[N], app[M], num, cnt, b[N], times[N];
ll pw[M][2], hs[N][2], sum, ans[N];
struct node {
    int x, y, ind;
    node (int x = 0, int y = 0, int i = 0) : x(x), y(y), ind(i) {}
    inline bool operator < (const node &a) const {
        if (bel[x] == bel[a.x])
            return (bel[x] & 1) ? y < a.y : y > a.y;
        return bel[x] < bel[a.x];
    }
}que[N];
map<pll, int> tab;

template <class T> inline void read(T &x) {
    x = 0;
    char ch = getchar(), w = 0;
    while (!isdigit(ch)) w = (ch == '-'), ch = getchar();
    while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
    x = w ? -x : x;
    return;
}

inline void add(int p) {
    sum += times[b[p]], ++times[b[p]];
    return;
}

inline void del(int p) {
    --times[b[p]], sum -= times[b[p]];
    return;
}

int main() {
    int x, y;
    read(n);
    int maxA = 0;
    for (R int i = 1; i <= n; ++i)
        read(a[i]), maxA = max(maxA, a[i]);
    pw[0][0] = pw[0][1] = 1;
    for (R int i = 1; i <= maxA; ++i)
        pw[i][0] = pw[i - 1][0] * base[0] % mod[0], pw[i][1] = pw[i - 1][1] * base[1] % mod[1];
    tab[mp(0, 0)] = cnt = 1;
    for (R int i = 1; i <= n; ++i) {
        if (app[a[i]]) {
            hs[i][0] = (hs[i - 1][0] + mod[0] - pw[a[i]][0]) % mod[0];
            hs[i][1] = (hs[i - 1][1] + mod[1] - pw[a[i]][1]) % mod[1];
        }
        else {
            hs[i][0] = (hs[i - 1][0] + pw[a[i]][0]) % mod[0];
            hs[i][1] = (hs[i - 1][1] + pw[a[i]][1]) % mod[1];
        }
        app[a[i]] ^= 1;
        pll now = mp(hs[i][0], hs[i][1]);
        if (tab.find(now) == tab.end())
            tab[now] = ++cnt;
        b[i] = tab[now];
    }
    read(q);
    B = max(1, (int) (n / sqrt(q)));
    for (R int i = 0; i < n; ++i)
        bel[i + 1] = i / B + 1;
    for (R int i = 1; i <= q; ++i)
        read(x), read(y), que[++num] = node(x - 1, y, i);
    sort(que + 1, que + 1 + q);
    int p1 = 0, p2 = 0;
    times[1] = b[0] = 1;
    for (R int i = 1; i <= q; ++i) {
        while (p2 < que[i].y) add(++p2);
        while (p1 > que[i].x) add(--p1);
        while (p1 < que[i].x) del(p1++);
        while (p2 > que[i].y) del(p2--);
        ans[que[i].ind] = sum;
    }
    for (R int i = 1; i <= q; ++i)
        printf("%lld\n", ans[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/suwakow/p/11680264.html

时间: 2024-10-20 18:31:51

[SOJ475]【SPC #2】美丽的序列 ~ Beautiful Sequence【莫队】【哈希】的相关文章

[bzoj4540][Hnoi2016]序列——单调栈+莫队+RMQ

题目大意: 给定一个序列,每次询问一个区间[L,R]所有子区间的最小值之和. 思路: 考虑莫队如何转移,新增一个端点R,则增加的区间为[L...R-1,R],考虑这些区间新贡献的最小值. 我们把从R开始向左单调下降的序列给求出来,不难发现最小值是由区间内包含的最靠左一个在单调下降序列里的元素的值所决定的. 于是我们利用单调栈求出每一个元素前面第一个小于它的元素\(pre_i\),并求出以这个元素结尾的所有区间的最小值的和\(f_i\),不难发现\(f_i=f_{pre_i}+(i-pre_i)\

【DFS序列】【莫队算法】【权值分块】bzoj2809 [Apio2012]dispatching

题意:在树中找到一个点i,并且找到这个点子树中的一些点组成一个集合,使得集合中的所有点的c之和不超过M,且Li*集合中元素个数和最大 首先,我们将树处理出dfs序,将子树询问转化成区间询问. 然后我们发现,对于单一节点来说,“使得集合中的所有点的c之和不超过M,且Li*集合中元素个数和最大”可以贪心地搞,即优先选择c较小的点.(<--这正是主席树/权值线段树/权值分块的工作) 但是我们需要枚举所有节点,从他们中选一个最大的. 既然有dfs序了,那么就是无修改的区间询问咯.(<--莫队的工作)

hihoCoder 1596 Beautiful Sequence 搜索

Beautiful Sequence Description 对于一个正整数列a[1], ... , a[n] (n ≥ 3),如果对于所有2 ≤ i ≤ n - 1,都有a[i-1] + a[i+1] ≥ 2 × a[i],则称这个数列是美丽的. 现在有一个正整数列b[1], ..., b[n],请计算:将b数列均匀随机打乱之后,得到的数列是美丽的概率P. 你只需要输出(P × (n!))mod 1000000007即可.(显然P × (n!)一定是个整数) Input 第一行一个整数n. (

Beautiful Sequence

Beautiful Sequence 给定一些数(可能相同),将它们随机打乱后构成凹函数,求概率 .N<=60 . 首先,这种题求概率事实上就是求方案.所以现在要求的是用这些数构成凹函数的方案数. 依稀记得上次的一道考试题,只是把凹函数变成了一个具有特殊性质的单调序列而已.这道题也是一样,由于它不关心数的位置,所以把数排序以后,可以统计把当前数插入凹函数的方案. exp1:与数的位置无关的计数题可以考虑排序. 用\(f[i][j][k][l]\)表示凹函数最左边的两个点,最右边的两个点.那么新来

UML之序列图(Sequence Diagram)

类图描述的是类之间的静态关系,而序列图展示的是对象之间的沟通方法,描述运行时的交互关系. OOP编程语言里面合理的直接交互方式只有一种,方法调用(Event通讯是间接的).所以序列图也可以 理解为方法调用交互图.方法调用有四个元素,参与者(两个,调用者和被调用者),方法名称,输入 和输出. 参与者 参与者用一个Lifeline来表示,图像为一个矩形外加底部的一条竖线.矩形里面显示对象名,格式为 name:ClassType的样式,都为可选项,Martin Fowler推荐a Handler的格式

【BZOJ1345】[Baltic2007]序列问题Sequence 贪心+单调栈

[BZOJ1345][Baltic2007]序列问题Sequence Description 对于一个给定的序列a1, …, an,我们对它进行一个操作reduce(i),该操作将数列中的元素ai和ai+1用一个元素max(ai,ai+1)替代,这样得到一个比原来序列短的新序列.这一操作的代价是max(ai,ai+1).进行n-1次该操作后,可以得到一个长度为1的序列.我们的任务是计算代价最小的reduce操作步骤,将给定的序列变成长度为1的序列. Input 第一行为一个整数n( 1 <= n

bzoj1345[Baltic2007]序列问题Sequence*

bzoj1345[Baltic2007]序列问题Sequence 题意: n个数,合并ai和ai+1可以得到max(ai,ai+1),代价为max(ai,ai+1).问合并n-1次最小代价为多少.n≤1000000. 题解: (来自题解,因为我不知道为什么这样做)维护一个单调递减栈.对于每个加入的元素,若加入后不满足单调性质,则让其与栈顶-1的元素比较:如果加入的数大,则合并栈顶和栈顶-1的数(把栈顶去掉),费用为栈顶-1:否则合并当前与栈顶的数(把栈顶去掉),费用为当前数.重复上述操作,直到满

Oracle修改序列(Sequence)起始值的方法

Oracle修改序列(Sequence)起始值的方法 Oracle 序列(Sequence)主要用于生成流水号,在应用中经常会用到,特别是作为ID值,拿来做表主键使用较多. 但是,有时需要修改序列初始值(START WITH)时,有同仁使用这个语句来修改:alter sequence sequencename start with xxxxxxxx.但是,在Oracle DB中,修改序列没有这样的语法.下面介绍几种修改方式: 1.先删除序列,然后重新创建.不过这不是当前要讲的重点.这个方法比较暴

美丽的序列

题目背景 Background GD是一个热衷于寻求美好事物的人,一天他拿到了一个美丽的序列. 题目描述 Description 为了研究这个序列的美丽程度,GD定义了一个序列的“美丽度”和“美丽系数”:对于这个序列的任意一个区间[l,r],这个区间的“美丽度”就是这个区间的长度与这个区间的最小值的乘积,而整个序列的“美丽系数”就是它的所有区间的“美丽度”的最大值.现在GD想要你帮忙计算这个序列的“美丽系数”. 输入输出格式 Input/output 输入格式: 第一行一个整数n,代表序列中的元