SCUT - G - 魔法项链 - 树状数组

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\n", 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\n", ans[i]);
    return 0;
}
posted @ 2019-08-12 22:27  韵意  阅读(156)  评论(0编辑  收藏  举报