https://scut.online/contest/30/G
很久以前做的一个东西,当时是对R排序之后树状数组暴力统计当前区间的前缀和。每有一个元素出现在R的范围内,就解除他的同样元素的影响,在他上一个同样元素曾经+1的位置给他-1。因为已经对R进行排序了,下一个询问一定会更容易包含后面出现的那一个。
今天又演了居然想尺取,做不到做不到,L是会不断变化的,不满足尺取的条件。
然后重写的时候发现
last[a[R]]=R++;
与
last[a[R]]=R;
++R;
并不等价。
看来会改变的同一个变量最好只在一句话中出现一次。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Query {
int l, r, id;
} q[1000005];
bool cmp1(const Query& q1, const Query& q2) {
return q1.r != q2.r ? q1.r < q2.r : q1.l < q2.l;
}
int ans[1000005];
int n, m, a[1000005];
int last[1000005], cnt;
int bit[1000005];
inline int Sum(int x) {
int res = 0;
for(; x; x -= x & -x)
res += bit[x];
return res;
}
inline void Add(int x, int v) {
for(; x <= n; x += x & -x)
bit[x] += v;
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[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, cmp1);
int R = 1;
for(int i = 1; i <= m; ++i) {
while(R <= q[i].r) {
if(last[a[R]])
Add(last[a[R]], -1);
Add(R, 1);
last[a[R]] = R;
++R;
}
ans[q[i].id] = Sum(q[i].r) - Sum(q[i].l - 1);
}
for(int i = 1; i <= m; ++i)
printf("%d
", ans[i]);
return 0;
}
在不引起混淆的情况下,使用运算符重载会比使用外部cmp快10%。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
struct Query {
int l, r, id;
bool operator<(const Query& q2) {
return r < q2.r;
}
} q[1000005];
int ans[1000005];
int n, m, a[1000005];
int last[1000005], cnt;
int bit[1000005];
inline int Sum(int x) {
int res = 0;
for(; x; x -= x & -x)
res += bit[x];
return res;
}
inline void Add(int x, int v) {
for(; x <= n; x += x & -x)
bit[x] += v;
}
int main() {
#ifdef Yinku
freopen("Yinku.in", "r", stdin);
#endif // Yinku
scanf("%d", &n);
for(int i = 1; i <= n; ++i)
scanf("%d", &a[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);
int R = 1;
for(int i = 1; i <= m; ++i) {
while(R <= q[i].r) {
if(last[a[R]])
Add(last[a[R]], -1);
Add(R, 1);
last[a[R]] = R;
++R;
}
ans[q[i].id] = Sum(q[i].r) - Sum(q[i].l - 1);
}
for(int i = 1; i <= m; ++i)
printf("%d
", ans[i]);
return 0;
}