刚刚用 P1972 [SDOI2009]HH的项链 练了一下莫队模板(虽然现在莫队卡不大过去了),发现操作区间端点左右移动时,以下两种写法的常数差别很大,希望有大佬能说明以下原因。
//这是复杂度优秀的一种
while(l > Q[k].l) ans += (cnt[d[--l]]++ == 0 ? 1 : 0);
//这种就要几乎慢上一倍
while(l > Q[k].l) if(cnt[d[--l]]++ == 0) ans++;
完整代码如下
//faster
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
inline int read();
const int N = 1e6 + 10;
int n, m, l, r, d[N], cnt[N], Ans[N], ans, siz;
struct node
{
int l, r, b, id;
bool operator < (const node & other ) const
{
return b ^ other.b ? l < other.l : ((b & 1) ? r<other.r : r>other.r);
}
} Q[N];
signed main()
{
n = read();
for(register int k = 1; k <= n; k++)
d[k] = read();
m = read(), siz = n / sqrt(m * 2 / 3);
for(register int k = 1; k <= m; Q[k].id = k, k++)
Q[k].l = read(), Q[k].r = read(), Q[k].b = Q[k].l / siz;
sort(&Q[1], &Q[m + 1]);
for(register int k = Q[1].l; k <= Q[1].r; k++)
if(cnt[d[k]]++ == 0) ans++;
l = Q[1].l, r = Q[1].r;
for(register int k = 1; k <= m; k++)
{
// 问题就出现在这一段上
while(l > Q[k].l) ans += (cnt[d[--l]]++ == 0 ? 1 : 0);
while(r < Q[k].r) ans += (cnt[d[++r]]++ == 0 ? 1 : 0);
while(l < Q[k].l) ans -= (--cnt[d[l++]] == 0 ? 1 : 0);
while(r > Q[k].r) ans -= (--cnt[d[r--]] == 0 ? 1 : 0);
//-------------------------------------------------
Ans[Q[k].id] = ans;
}
for(register int k = 1; k <= m; k++)
printf("%d\n", Ans[k]);
return 0;
}
inline char new_getchar()
{
static char sz[2048];
static int size = 0, wz = 0;
if(size == wz)
{
wz = 0;
size = fread(sz, 1, 2048, stdin);
if(wz != size)
return sz[wz++];
else
return EOF;
}
else
return sz[wz++];
}
inline int read()
{
int neg = 1, x = 0, ch = '~';
while(!(ch >= '0' && ch <= '9')) neg = (ch == '-') ? -1 : 1, ch = getchar();
while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) , x += ch - '0', ch = getchar();
return x * neg;
}
//slower
#include <cmath>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
inline int read();
const int N = 1e6 + 10;
int n, m, l, r, d[N], cnt[N], Ans[N], ans, siz;
struct node
{
int l, r, b, id;
bool operator < (const node & other ) const
{
return b ^ other.b ? l < other.l : ((b & 1) ? r<other.r : r>other.r);
}
} Q[N];
signed main()
{
n = read();
for(register int k = 1; k <= n; k++)
d[k] = read();
m = read(), siz = n / sqrt(m * 2 / 3);
for(register int k = 1; k <= m; Q[k].id = k, k++)
Q[k].l = read(), Q[k].r = read(), Q[k].b = Q[k].l / siz;
sort(&Q[1], &Q[m + 1]);
for(register int k = Q[1].l; k <= Q[1].r; k++)
if(cnt[d[k]]++ == 0) ans++;
l = Q[1].l, r = Q[1].r;
for(register int k = 1; k <= m; k++)
{
// 问题就出现在这一段上
while(l > Q[k].l) if(cnt[d[--l]]++ == 0) ans++;
while(r < Q[k].r) if(cnt[d[++r]]++ == 0) ans++;
while(l < Q[k].l) if(--cnt[d[l++]] == 0) ans--;
while(r > Q[k].r) if(--cnt[d[r--]] == 0) ans--;
//-------------------------------------------------
Ans[Q[k].id] = ans;
}
for(register int k = 1; k <= m; k++)
printf("%d\n", Ans[k]);
return 0;
}
inline char new_getchar()
{
static char sz[2048];
static int size = 0, wz = 0;
if(size == wz)
{
wz = 0;
size = fread(sz, 1, 2048, stdin);
if(wz != size)
return sz[wz++];
else
return EOF;
}
else
return sz[wz++];
}
inline int read()
{
int neg = 1, x = 0, ch = '~';
while(!(ch >= '0' && ch <= '9')) neg = (ch == '-') ? -1 : 1, ch = getchar();
while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) , x += ch - '0', ch = getchar();
return x * neg;
}