莫队算法

China☆狼群 提交于 2020-02-06 02:39:30

 

今天学习了莫队算法,精髓就是处理区间问题。

重点是分块,和指针移动。

/*
学习莫队算法,重点是分块和区间维护
 */
/*例如题目,区间内查询数字num出现次数
*/
#include <iostream>
#include <algorithm>
#include <cmath>
using namespace std;
const int maxn = 50000 + 100;
int n;// input n number to arr
int num;//查询的数字
int arr[maxn];
int ans[maxn];
int sum;
int block;
struct node
{
    int left, right;
    int pos;
}query[maxn];
bool cmp(const node &a,const node &b){
    if(a.left / block == b.left / block)
        //同一块的时候
        return a.right < b.right;
    //不同块的时候
    return a.left < b.left;
}
void add(int index){
    if(arr[index] == num)
        sum++;
}
void sub(int index){
    if(arr[index] == num)
        sum--;
}
int main(int argc, char const *argv[])
{
    int m;//m次查询
    cin>>n>>num>>m;
    for (int i = 0; i < n; ++i)
        cin>>arr[i];
    for (int i = 0; i < m; ++i){
        cin>>query[i].left>>query[i].right;
        query[i].left--, query[i].right--;
        query[i].pos = i;
    }
    //分块和排序
    block = sqrt(n);
    //记得传递的是结构体
    sort(query, query + m, cmp);
    int now_left = 0, now_right = 0;
    sum = 0;
    add(0);
    for (int i = 0; i < m; ++i)
    {
        while(now_left < query[i].left) sub(now_left++);
        while(now_left > query[i].left) add(--now_left);
        while(now_right < query[i].right) add(++now_right);
        while(now_right > query[i].right) sub(now_right--);
        ans[query[i].pos] = sum;
    }
    for (int i = 0; i < m; ++i)
        cout<<ans[i]<<endl;
    return 0;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!