您的位置:首页 > 其它

bzoj 3339 莫队

2017-08-21 10:03 204 查看
题意:



求任意一个区间的SG函数。

想到线段树,但是线段树合并很麻烦。

线段树——分块。

分块的一个应用就是莫队算法。

怎么暴力递推呢?

从一个区间到另一个区间,Ans 取决于 Ans 和 加入和删除的这个数的大小比较。加入一个新数,可能导致Ans 变大,变到哪里去呢? 用一个cnt记录出现数值的个数。

变大到cnt=0的地方。

减去一个数,可能导致Ans 变小。这时就要看cnt 和 大小比较了。

#include <bits/stdc++.h>

using namespace std;

const int maxn = 200011*41;

int N,M;
int a[maxn];
int pos[maxn];
int ans[maxn];
int cnt[maxn];

int Ans;

struct  Node {
int l,r;
int id;
}nodes[maxn];

bool cmp(Node a,Node b) {
if(pos[a.l]==pos[b.l])
return a.r < b.r;
return pos[a.l] < pos[b.l];
}

void add(int x)
{
cnt[x]++;
if(Ans==x)
while(cnt[Ans])
Ans++;
}

void del(int x)
{
cnt[x]--;
if(cnt[x]==0&&x<Ans)Ans=x;
}

int main(int argc, char const *argv[])
{
scanf("%d%d",&N,&M);

int sz =ceil(sqrt(1.0*N));
for(int i=1; i <=N; i++) {
scanf("%d",&a[i]);
pos[i] = (i-1)/sz;
}

for(int i=1; i <= M; i++) {
scanf("%d%d",&nodes[i].l,&nodes[i].r);
nodes[i].id = i;
}

sort(nodes+1,nodes+1+M,cmp);

int L = 1,R = 0;
Ans = 0;

for(int i=1;i<=M;i++)
{
int id = nodes[i].id;
while(R<nodes[i].r)R++,add(a[R]);
while(L>nodes[i].l)L--,add(a[L]);
while(R>nodes[i].r)del(a[R]),R--;
while(L<nodes[i].l)del(a[L]),L++;
ans[id]=Ans;
}

for(int i=1; i <= M; i++)
printf("%d\n", ans[i]);

return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: