转自:https://www.cnblogs.com/WAMonster/p/10118934.html
不需要修改值的莫队
题目链接:https://vjudge.net/problem/SPOJ-DQUERY#author=0
题意:求区间内不同的数的个数
把整个区间分块后排序,用双指针移动解决。
指针移动优化
while(l < ql) now -= !--cnt[aa[l++]];
while(l > ql) now += !cnt[aa[--l]]++;
while(r < qr) now += !cnt[aa[++r]]++;
while(r > qr) now -= !--cnt[aa[r--]];
普通排序函数
最好先用这个,如果超时再用优化排序 优化排序某些题可能会过不了 如hdu6333
int cmp(query a, query b) {
return belong[a.l] == belong[b.l] ? a.r < b.r : belong[a.l] < belong[b.l];
}
还可以加读入输出优化
最好把分块的大小改成 n
2
3
\frac{2}{3}
32 会更快
n
\sqrt{n}
n可能会退化
#include<cstdio>
#include<iostream>
#include<algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
using namespace std;
const int maxn=15e5+5;
const int maxm=1e6+5;
int aa[maxn],cnt[maxm],ans[maxn],belong[maxn],now;
struct NODE
{
int l,r,id;
} q[maxn];
int cmp(NODE a, NODE b)//玄学排序
{
return (belong[a.l] ^ belong[b.l]) ? belong[a.l] < belong[b.l] : ((belong[a.l] & 1) ? a.r < b.r : a.r > b.r);
}
int main()
{
int n,m;
scanf("%d",&n);
int sz=sqrt(n);
int bnum=ceil((double)n/sz);
for(int i=1; i<=bnum; i++)
{
for(int j=(i-1)*sz+1; j<=i*sz; j++)
{
belong[j]=i;
}
}
for(int i=1; i<=n; i++)
{
scanf("%d",&aa[i]);
}
scanf("%d",&m);
for(int i=1; i<=m; i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].id=i;
}
sort(q+1,q+1+m,cmp);
int l=1,r=0;
for(int i=1; i<=m; i++)
{
int ql=q[i].l,qr=q[i].r;
while(l<ql)
{
--cnt[aa[l]];
if(!cnt[aa[l]])
now--;
l++;
}
while(l>ql)
{
l--;
if(!cnt[aa[l]])
now++;
++cnt[aa[l]];
}
while(r<qr)
{
r++;
if(!cnt[aa[r]])
now++;
++cnt[aa[r]];
}
while(r>qr)
{
--cnt[aa[r]];
if(!cnt[aa[r]])
now--;
r--;
}
ans[q[i].id]=now;
}
for(int i=1; i<=m; i++)
printf("%d\n",ans[i]);
return 0;
}
带单点修改的莫队
题目链接:https://vjudge.net/problem/HYSBZ-2120
单点修改就多了一个指针time,表示当前询问所在的时间顺序,每次查询时time移动并且修改cnt,同时更改值。
排序函数也需要修改一下。
time指针优化
while(time < qt) {
++time;
if(ql <= c[time].pos && c[time].pos <= qr) now -= !--cnt[a[c[time].pos]] - !cnt[c[time].color]++;
swap(a[c[time].pos], c[time].color);
}
while(time > qt) {
if(ql <= c[time].pos && c[time].pos <= qr) now -= !--cnt[a[c[time].pos]] - !cnt[c[time].color]++;
swap(a[c[time].pos], c[time].color);
--time;
}
#include<cstdio>
#include<iostream>
#include<algorithm>
#include <cstring>
#include <cmath>
#include <cstdio>
using namespace std;
const int maxn=1e4+5;
const int maxm=1e6+5;
int a[maxn],cnt[maxm],ans[maxn],belong[maxn];
struct query
{
int l,r,time,id;
} q[maxn];
struct modify
{
int pos,color,last;
} c[maxn];
int cntq,cntc,n,m,sz,bnum;
int cmp(query a, query b)
{
return (belong[a.l] ^ belong[b.l]) ? belong[a.l] < belong[b.l] : ((belong[a.r] ^ belong[b.r]) ? belong[a.r] < belong[b.r] : a.time < b.time);
}
int main()
{
scanf("%d%d",&n,&m);
getchar();
sz=pow(n,2.0/3.0);
bnum=ceil((double)n/sz);
for(int i=1; i<=bnum; i++)
{
for(int j=(i-1)*sz+1; j<=i*sz; j++)
{
belong[j]=i;
}
}
for(int i=1; i<=n; i++)
{
scanf("%d",&a[i]);
getchar();
}
for(int i=1; i<=m; i++)
{
char ss[100];
int x,y;
scanf("%s",ss);
getchar();
scanf("%d%d",&x,&y);
getchar();
if(ss[0]=='Q')
{
q[++cntq].l=x;
q[cntq].r=y;
q[cntq].time=cntc;
q[cntq].id=cntq;
}
else if(ss[0]=='R')
{
c[++cntc].pos=x;
c[cntc].color=y;
}
}
sort(q+1,q+cntq+1,cmp);
int l=1,r=0,time=0,now=0;
for(int i=1; i<=cntq; i++)
{
int ql=q[i].l,qr=q[i].r,qt=q[i].time;
while(l<ql)
{
--cnt[a[l]];
if(!cnt[a[l]])
now--;
l++;
}
while(l>ql)
{
l--;
if(!cnt[a[l]])
now++;
++cnt[a[l]];
}
while(r<qr)
{
r++;
if(!cnt[a[r]])
now++;
++cnt[a[r]];
}
while(r>qr)
{
--cnt[a[r]];
if(!cnt[a[r]])
now--;
r--;
}
while(time<qt)
{
++time;
if(ql<=c[time].pos&&c[time].pos<=qr)
{
cnt[a[c[time].pos]]--;
if(!cnt[a[c[time].pos]])
now--;
if(!cnt[c[time].color])
now++;
cnt[c[time].color]++;
}
swap(a[c[time].pos],c[time].color);
}
while(time>qt)
{
if(ql<=c[time].pos&&c[time].pos<=qr)
{
cnt[a[c[time].pos]]--;
if(!cnt[a[c[time].pos]])
now--;
if(!cnt[c[time].color])
now++;
cnt[c[time].color]++;
}
swap(a[c[time].pos],c[time].color);
time--;
}
ans[q[i].id]=now;
}
for(int i=1; i<=cntq; i++)
{
printf("%d\n",ans[i]);
}
return 0;
}