Codeforces 387E 树状数组

来源:互联网 发布:淘宝兰亭序放大版字帖 编辑:程序博客网 时间:2024/06/01 10:32

http://codeforces.com/problemset/problem/387/E


记录每个数的下标,对数从小到大考虑。如果该数需要保留,那么就往set中插入该数的下标。否则可以查询出当前数左边和右边第一个比它小的数的下标,可以统计这个区间中已经删掉的数的数量,就可以计算出当前数的贡献。


#include<bits/stdc++.h>using namespace std;const int MAX_LEN = 1e6+10;typedef long long ll;int n, m;ll tree[MAX_LEN];int id[MAX_LEN], keep[MAX_LEN];void add(int pos, int value){    while(pos <= n){        tree[pos] += value;        pos += (pos&-pos);    }    return ;}ll query(int l, int r){    int ans = 0;    while(r){        ans += tree[r];        r -= (r&-r);    }    while(l){        ans -= tree[l];        l -= (l&-l);    }    return ans;}set<int> se;set<int> reverseSe;int main(){    std::ios::sync_with_stdio(false);    memset(keep, false, sizeof(keep));    scanf("%d%d",&n, &m);    int tmp;    for (int i = 1; i <= n; i++)        scanf("%d", &tmp), id[tmp] = i;    for (int i = 1; i <= m; i++)        scanf("%d", &tmp), keep[tmp] = true;    se.insert(0); se.insert(n+1);    reverseSe.insert(0); reverseSe.insert(-n-1);    if (n == m){        cout << 0 << endl;        return 0;    }    ll ans = 0;    for (int i = 1; i <= n; i++){        if (keep[i])            se.insert(id[i]), reverseSe.insert(-id[i]);        else{            int l = -*reverseSe.upper_bound(-id[i]);            int r = *se.upper_bound(id[i]);            //cout << "l: " << l << " r: " << r << endl;            ans += r-l-1;            ans -= query(l, r-1);            add(id[i], 1);        }    }    printf("%I64\n", ans);    return 0;}


阅读全文
0 0
原创粉丝点击