hdu3333-Turing Tree-线段树+离线+离散化

前言:引用某某的话——我是猪QAQ。。。。。

题意就不复述了。

解题思路:

一般的建树,求和。

离散化:用另一个数组sor[]记录原数组,sort一遍,用unique去重,用sor[]数组元素下标,代替原数组中元素,然后在sor[]数组里二分查找元素,last[]数组记录第i个元素上一次出现的位置。

离线处理:将查询按右边界从小到大排序,依次处理区间[1, r1]、[r1+1, r2]、[r2+1, r3]......将重复的元素的前一个(记录在last里)在线段树里单点更新删去, 然后将query(li, ri)的值记录到相应的位置。同时,在读入时记录是第几个查询用于后面输出。

复杂度:O(nlogn)

AC代码:

  1 #include <iostream>

  2 #include <cstdio>

  3 #include <vector>

  4 #include <cstring>

  5 #include <algorithm>

  6 using namespace std;

  7 #define lson l, m, rt<<1

  8 #define rson m+1, r, rt<<1|1

  9 int n, m;

 10 struct node

 11 {

 12     int l, r;

 13     int num;

 14     bool operator < (const node that) const{

 15         return r < that.r;

 16     }

 17 };

 18 bool uni(int i, int j)

 19 {

 20     return i == j;

 21 }

 22 vector<node> brr;

 23 vector<int> sor;

 24 vector<int> arr;

 25 long long sgt[1200080];

 26 int last[30005];

 27 long long ans[300005];

 28 void input()

 29 {

 30     brr.clear(); sor.clear(); arr.clear();

 31     memset(last, -1, sizeof(last));

 32     scanf("%d", &n);

 33     for(int i = 0; i < n; i++) {

 34         int a; scanf("%d", &a);

 35         arr.push_back(a);

 36         sor.push_back(a);

 37     }

 38     sort(sor.begin(), sor.end());

 39     vector<int>::iterator it;

 40     it = unique(sor.begin(), sor.end(), uni);

 41     sor.resize(distance(sor.begin(), it)); //离散化

 42     scanf("%d", &m);

 43     for(int i = 0; i < m; i++) {

 44         node x; scanf("%d%d", &x.l, &x.r);

 45         x.num = i;   //记录询问的顺序

 46         brr.push_back(x);

 47     }

 48     sort(brr.begin(), brr.end());

 49 }

 50 void push_up(int rt)

 51 {

 52     sgt[rt] = sgt[rt<<1] + sgt[rt<<1|1];

 53 }

 54 void build(int l, int r, int rt)

 55 {

 56     if(l == r) {

 57         sgt[rt] = arr[l-1];

 58         return;

 59     }

 60     int m = (l + r)>>1;

 61     build(lson);

 62     build(rson);

 63     push_up(rt);

 64 }

 65 void Delete(int l, int r, int rt, int pos)

 66 {

 67     if(l == r) {

 68         sgt[rt] = 0; return ;

 69     }

 70     int m = (l+r)>>1;

 71     if(pos <= m) Delete(lson, pos);

 72     else Delete(rson, pos);

 73     push_up(rt);

 74 }

 75 long long query(int l, int r, int rt, int L, int R)

 76 {

 77     if(L <= l && r <= R) {

 78         return sgt[rt];

 79     }

 80     long long res = 0;

 81     int m = (l+r)>>1;

 82     if(L <= m) res += query(lson, L, R);

 83     if(m < R) res += query(rson, L, R);

 84     return res;

 85 }

 86 

 87 void work()

 88 {

 89     build(1, n, 1);

 90     int l, r;

 91     for(int i = 0; i < m; i++) {

 92         r = brr[i].r-1;

 93         if(i == 0) l = 0;

 94         else l = brr[i-1].r;

 95         for(int j = l; j <= r; j++) {

 96             int pos = lower_bound(sor.begin(), sor.end(), arr[j]) - sor.begin();   //pos对应离散化后的元素下标

 97             if(last[pos] == -1) {   //前面无重复

 98                 last[pos] = j; continue;

 99             }

100             Delete(1, n, 1, last[pos]+1); last[pos] = j;  //删除重复元素,更改last为元素当前位置。

101         }

102         ans[brr[i].num] = query(1, n, 1, brr[i].l, brr[i].r);   //将结果填在询问的顺序位置

103     }

104     for(int i = 0; i < m; i++) {

105         printf("%I64d\n", ans[i]);

106     }

107 }

108 int main()

109 {

110     int t; cin>>t;

111     while(t--) {

112         input();

113         work();

114     }

115     return 0;

116 }
View Code

 

你可能感兴趣的:(tree)