今天学习了莫队算法,精髓就是处理区间问题。
重点是分块,和指针移动。
/*
学习莫队算法,重点是分块和区间维护
*/
/*例如题目,区间内查询数字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;
}
来源:CSDN
作者:ZZULI_星.夜
链接:https://blog.csdn.net/weixin_43906799/article/details/104180578