hdu3874一维树状数组+离线算法

这题开始一直不会,查解题报告,都看不懂,后来还是自己想明白了……其实这个题目的难点就在于重复值不能重复算(假设没有重复值就是一道很水的树状数组题了,甚至都可以不用树状数组),所以这题突破点就是消除重复值带来的影响。如何消除呢?其实也不难。我们先局部地看这个问题,数据不是一次性加入树状数组里,而是一个个地加。假设有两个查询(1, y1)和(x2, y2)其中y1<y2。假设[1, y1]之间没有重复的数,那么我们把这些数插入一个树状数组里就能解决问题(logn时间查出结果)。然后到了操作(x2,y2),因为y2比y1大,在y1到y2之间可能有些数在[1,y1]已经出现过了,那么我们如何处理呢?没错!删掉前面那个,保留当前这个!(这个不理解的慢慢想,想清楚别的就简单了)这样我们又解决了(x2,y2)的查询,并且树状数组里维护的依然没有重复的数,依此类推,就能解决问题。当然,这是需要离线做的,先把所有数和操作都存起来,把操作按y从小到大排序,按排好的顺序一个个地处理每个操作。

/*

 * hdu3874/win.cpp

 * Created on: 2012-11-1

 * Author    : ben

 */

#include <cstdio>

#include <cstdlib>

#include <cstring>

#include <cmath>

#include <ctime>

#include <iostream>

#include <algorithm>

#include <queue>

#include <set>

#include <map>

#include <stack>

#include <string>

#include <vector>

#include <deque>

#include <list>

#include <functional>

#include <numeric>

#include <cctype>

using namespace std;

const int MAXN = 50100;

const int MAXQ = 2000010;

typedef long long typec;

typedef struct Query{

    int pos, x, y;

    typec result;

}Query;

inline bool cmppos(const Query &q1, const Query &q2) {

    return q1.pos < q2.pos;

}

inline bool cmpy(const Query &q1, const Query &q2) {

    return q1.y < q2.y;

}

inline int lowbit(int x) {

    return x & (-x);

}

int N, Q;

Query query[MAXQ];

map<int, int> lastpos;

typec data[MAXN];//存储数据,下标从1开始

int inputdata[MAXN];

//查询data[1...pos]的和

typec sum(int pos) {

    typec ret = 0;

    for(int i = pos; i > 0; i -= lowbit(i)) {

        ret += data[i];

    }

    return ret;

}

//修改data[pos]的值,在原来基础上加value

void modify(int pos, typec value) {

    for (int i = pos; i <= N; i += lowbit(i)) {

        data[i] += value;

    }

}

void insert(int pos, int value) {

    if(lastpos[value] != 0) {

        modify(lastpos[value], -value);

    }

    lastpos[value] = pos;

    modify(pos, value);

}

int main() {

#ifndef ONLINE_JUDGE

    freopen("data.in", "r", stdin);

#endif

    int T;

    scanf("%d", &T);

    while(T--) {

        lastpos.clear();

        scanf("%d", &N);

        for(int i = 1; i <= N; i++) {

            scanf("%d", &inputdata[i]);

        }

        scanf("%d", &Q);

        for(int i = 0; i < Q; i++) {

            scanf("%d%d", &query[i].x, &query[i].y);

            query[i].pos = i;

        }

        sort(query, query + Q, cmpy);

        fill(data, data + N + 1, 0);

        int I = 1;

        for(int i = 0; i < Q; i++) {

            while(I <= query[i].y && I <= N) {

                insert(I, inputdata[I]);

                I++;

            }

            query[i].result = sum(query[i].y) - sum(query[i].x - 1);

        }

        sort(query, query + Q, cmppos);

        for(int i = 0; i < Q; i++) {

            printf("%I64d\n", query[i].result);

        }

    }

    return 0;

}

你可能感兴趣的:(树状数组)