题目链接
题意
给定一个序列,离线查询多组区间,区间内可任意排列,求最少分成几个连续的序列。
思路
刚开始以为不能任意排列,感觉是RMQ怼了一下发现样例过不了。如果是不能任意排列的串,能不能用RMQ怼,哪位大佬能抬一手ORZ。
算法教程网上多如牛毛这里不再提,开个mp数组,O(1)维护一下相邻区间的转移方法,具体方法参考代码ins,mov函数部分。
此博客主要记录模板自己参考
代码
#include<bits/stdc++.h>
using namespace std;
struct Node
{
int l, r, id;
}e[100005];
int blo, v[100005], tmp, ans[100005], mp[100005];
bool cmp(Node a, Node b)
{
if(a.l/blo == b.l/blo) return a.r < b.r;
return a.l < b.l;
}
void ins(int x)
{
if(mp[x+1] == 0 && mp[x-1] == 0) ++tmp;
if(mp[x+1] && mp[x-1]) --tmp;
mp[x] = 1;
}
void mov(int x)
{
if(mp[x+1] == 0 && mp[x-1] == 0) --tmp;
if(mp[x+1] && mp[x-1]) ++tmp;
mp[x] = 0;
}
int main()
{
int t;
for(scanf("%d",&t); t; --t)
{
int n, m;
scanf("%d%d",&n,&m);
blo = sqrt(n);
for(int i = 1; i <= n; ++i) scanf("%d",&v[i]);
for(int i = 0; i < m; ++i)
{
e[i].id = i;
scanf("%d%d",&e[i].l,&e[i].r);
}
sort(e,e+m,cmp);
int l = 1, r = 0;
tmp = 0;
memset(mp,0,sizeof(mp));
for(int i = 0; i < m; ++i)
{
while(r < e[i].r) ins(v[++r]);
while(r > e[i].r) mov(v[r--]);
while(l < e[i].l) mov(v[l++]);
while(l > e[i].l) ins(v[--l]);
ans[e[i].id] = tmp;
}
for(int i = 0; i < m; ++i) printf("%d\n",ans[i]);
}
return 0;
}