HDU 3333 & 3874 (线段树+离线询问)

两个题目都是求区间之内,不重复的数字之和,3333需要离散化处理.................

调试了一下午........说多了都是泪...........

 

#include <iostream>
#include <algorithm>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <map>
#include <queue>
#include <climits>//形如INT_MAX一类的
#define MAX 51111
#define INF 0x7FFFFFFF
#define L(x) x<<1
#define R(x) x<<1|1
//#pragma comment(linker, "/STACK:36777216") ///传说中的外挂
using namespace std;

inline void RD(int &ret) {
    char c;
    do {
        c = getchar();
    } while(c < '0' || c > '9') ;
    ret = c - '0';
    while((c=getchar()) >= '0' && c <= '9')
        ret = ret * 10 + ( c - '0' );
}

inline void OT(int a) {
    if(a >= 10)OT(a / 10) ;
    putchar(a % 10 + '0') ;
}

struct node {
    int l,r,mid,cover;
    __int64 sum;
} tree[MAX*4];

int n,m;
int a[MAX],va[MAX],pos[MAX],tmp[MAX];
__int64 ans[111111 * 2];

struct Node {
    int l,r;
    int id;
} qes[111111 * 2];

void init() {
    memset(va,0,sizeof(va));
}
int search(int l,int r,int x) {
    int mid;
    while(l <= r) {
        mid = (l+r) >> 1;
        if(pos[mid] == x) return mid;
        else if(pos[mid] > x) r = mid -1;
        else l = mid + 1;
    }
}

void up(int num) {
    tree[num].sum = tree[L(num)].sum + tree[R(num)].sum;
}

void build(int l,int r,int num) {
    tree[num].l = l;
    tree[num].r = r;
    tree[num].mid = (l+r) >> 1;
    tree[num].cover = 0;
    tree[num].sum = 0;
    if(l == r) {
        tree[num].sum = va[l];
        return ;
    }
    build(l,tree[num].mid,L(num));
    build(tree[num].mid + 1,r,R(num));
    up(num);
}

void update(int l,int x,int color) {
    if(tree[x].l == tree[x].r) {
        tree[x].sum += color;
        return ;
    }
    if(l > tree[x].mid) update(l,R(x),color);
    else update(l,L(x),color);
    up(x);
}

__int64 query(int l,int r,int num) {
    if(l == tree[num].l && tree[num].r == r) {
        return tree[num].sum;
    }
    if(r <= tree[num].mid) {
        return query(l,r,L(num));
    } else if(l > tree[num].mid) {
        return query(l,r,R(num));
    } else {
        return query(l,tree[num].mid,L(num)) + query(tree[num].mid+1,r,R(num));
    }
}


bool cmp(const Node &a,const Node &b) {
    if(a.r == b.r) return a.l < b.l;
    return a.r < b.r;
}

bool cmp2(const int &a, const int &b) {
    return a < b;
}
int main() {
    int T;
    cin >> T;
    while(T --) {
        init();
        RD(n);
        int t = 1;
        for(int i=1; i<=n; i++) {
            RD(a[i]);
            tmp[i] = a[i];
        }
        sort(tmp+1,tmp+1+n,cmp2);
        pos[1] = tmp[1];
        for(int i=2; i<=n; i++) {
            if(tmp[i] != tmp[i-1]) {
                pos[++t] = tmp[i];
            }
        }
        build(1,n,1);
        RD(m);
        for(int i=1; i<=m; i++) {
            RD(qes[i].l);
            RD(qes[i].r);
            qes[i].id = i;
        }
        sort(qes+1,qes+1+m,cmp);
        int order = 1;
        for(int i=1; i<=m; i++) {
            while(qes[i].r >= order) {
                int id = search(1,t,a[order]);
                int ps = va[id];
                if( ps != 0) update(ps,1,-a[order]);
                va[id] = order;
                update(va[id],1,a[order]);
                order ++;
            }
            ans[qes[i].id] = query(qes[i].l,qes[i].r,1);
        }
        for(int i=1; i<=m; i++) {
            printf("%I64d\n",ans[i]);
        }
    }
    return 0;
}


 

 

posted @ 2013-08-02 22:46  javawebsoa  Views(232)  Comments(0Edit  收藏  举报