bzoj 1106

思路:很容易就能想到统计没两对点之间的未匹配点的个数。 在想怎么用数据结构维护这个东西,

没有想到用树状数组能很巧妙地维护出来, 就写了个莫队。。。

 

莫队:暴力维护就好了。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int,int>
#define piii pair<int, pair<int,int> >

using namespace std;

const int N = 1e5 + 10;
const int M = 10 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-6;
const int B = 223;

int n, a[N], cnt[N], l, r, ret;
struct Qus {
    int l, r;
    bool operator < (const Qus &rhs) const {
        if(l / 233 == rhs.l / 233) return r < rhs.r;
        return l / 233 < rhs.l / 233;
    }
} qus[N];

inline void update(int x) {
    ret += cnt[a[x]] ? -1 : 1;
    cnt[a[x]] ^= 1;
}

int main() {
    scanf("%d", &n);
    n <<= 1;

    for(int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
        if(qus[a[i]].l) qus[a[i]].r = i - 1;
        else qus[a[i]].l = i + 1;
    }

    sort(qus + 1, qus + 1 + n / 2);
    l = 1, r = 0, ret = 0;
    LL ans = 0;

    for(int i = 1; i <= n / 2; i++) {
        int L = qus[i].l, R = qus[i].r;
        if(L > R) continue;

        while(r < R) update(++r);
        while(l > L) update(--l);
        while(r > R) update(r--);
        while(l < L) update(l++);

        ans += ret;
    }

    printf("%lld\n", ans / 2);
    return 0;
}
/*
*/

 

树状数组:

对于第一次遇到的数a[ i ], 我们往 i 位置加1, 对于第二次遇到的数,我们往 pre[ a[ i ] ] 位置减1,然后统计区间( pre[ a[ i ] ], i )的值加到答案中。

#include<bits/stdc++.h>
#define LL long long
#define fi first
#define se second
#define mk make_pair
#define pii pair<int,int>
#define piii pair<int, pair<int,int> >

using namespace std;

const int N = 1e5 + 10;
const int M = 10 + 7;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-6;

int n, a[N], pre[N];

void modify(int x, int v) {
    for(int i = x; i < N; i += i & -i)
        a[i] += v;
}

int query(int x) {
    int ans = 0;
    for(int i = x; i; i -= i & -i)
        ans += a[i];
    return ans;
}


int main() {
    scanf("%d", &n);
    LL ans = 0;
    for(int i = 1; i <= 2 * n; i++) {
        int x; scanf("%d", &x);
        if(!pre[x]) {
            pre[x] = i;
            modify(i, 1);
        } else {
            modify(pre[x], -1);
            ans += query(i) - query(pre[x]);
        }
    }

    printf("%lld\n", ans);
    return 0;
}
/*

*/

 

posted @ 2018-06-15 15:28  NotNight  阅读(114)  评论(0编辑  收藏  举报