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 }

时间: 2024-10-05 15:06:03

hdu3333-Turing Tree-线段树+离线+离散化的相关文章

玲珑oj 1117 线段树+离线+离散化,laz大法

1117 - RE:从零开始的异世界生活 Time Limit:1s Memory Limit:256MByte Submissions:438Solved:68 DESCRIPTION 486到了异世界,看到了一群可爱的妹子比如蕾姆啊,艾米莉亚啊,拉姆啊,白鲸啊,怠惰啊等等!有一天膜女告诉486说她的能力可能不能再用了,因为膜女在思考一个数据结构题,没心情管486了.486说我来帮你做,膜女说你很棒棒哦! 给一个集合,最开始为空(不是数学上的集合)五个操作: 1.插入x2.把小于x的数变成x3

hdu 3333 Turing Tree(线段树)

题目链接:hdu 3333 Turing Tree 题目大意:给定一个长度为N的序列,有M次查询,每次查询l,r之间元素的总和,相同元素只算一次. 解题思路:涨姿势了,线段树的一种题型,离线操作,将查询按照右区间排序,每次考虑一个询问,将mv ~ r的点全部标记为存在,并且对于每个位置i,如果A[i]在前面已经出现过了,那么将前面的那个位置减掉A[i],当前位置添加A[i],这样做维护了每个数尽量做,那么碰到查询,用sum[r] - sum[l-1]即可. #include <cstdio>

HDU4288-Coder(线段树+离线+离散化)

Coder Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3183    Accepted Submission(s): 1254 Problem Description In mathematics and computer science, an algorithm describes a set of procedures

hdu 4288 线段树+离线+离散化

http://acm.hdu.edu.cn/showproblem.php?pid=4288 开始的时候,果断TLE,做的方法是,线段树上仅仅维护%5==3的坐标,比如1 2 3 4 5 6 7  如果删除第三个数,就将3,6的位置全+1,就是向右偏移以为,但是求和还是很慢,所以即使10秒,还是TLE... 正确做法: 1.节点内维护sum[0...4]分别代表区间内%5==i的和 2.结点维护点的个数,cnt 3.离散化处理,然后每次插入时,经过的结点cnt+1或-1,叶子节点Sum[0]就是

HDU3333 Turing Tree(线段树)

题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=3333 Description After inventing Turing Tree, 3xian always felt boring when solving problems about intervals, because Turing Tree could easily have the solution. As well, wily 3xian made lots of new

Super Mario(线段树离线区间k值)

以前见过这题,没做出来,知道是离线处理,这次仔细想了下, 首先把出现的高度都map离散化一下,以离散化出来的数目g建树,把每个位置都开俩个vector,一个存以这个位置为L的询问,一个存以这个位置为R的询问. 然后从1-g 进行更新,假如当前i是以第j个区间的开始位置,那么这时就可以询问一下<=p[j].h的个数s,显然这时第J个区间多加的,需要减掉,p[j].sum-=s; 然后更新第i个数,update(a[i],1,g,1);再找到某第k区间是以i结尾的,那么依旧询问一下,得出s,p[k]

poj2528 Mayor&#39;s posters(线段树,离散化)

离散化的思想: 对于这样的数据 (3,10000), (9,1000000), (5,100000), (1,1000), (7,1000000) 我们可以将其处理为 (2,7), (5,9), (3,8), (1,6), (4,9) 我们再对离散化之后的数据进行处理就行了. 题目意思: n(n<=10000)个人依次贴海报,给出每张海报所贴的范围li,ri(1<=li<=ri<=10000000). 求出最后还能看见多少张海报. 参考代码: #include <iostre

gcd(线段树离线处理)——HDU 4630

对应HDU题目:点击打开链接 No Pain No Game Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 1801    Accepted Submission(s): 770 Problem Description Life is a game,and you lose it,so you suicide. But you can

poj2299--B - Ultra-QuickSort(线段树,离散化)

Ultra-QuickSort Time Limit: 7000MS   Memory Limit: 65536K Total Submissions: 41215   Accepted: 14915 Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swappin

HDU 4107 Gangster Segment Tree线段树

这道题也有点新意,就是需要记录最小值段和最大值段,然后成段更新这个段,而不用没点去更新,达到提高速度的目的. 本题过的人很少,因为大部分都超时了,我严格按照线段树的方法去写,一开始居然也超时. 然后修补了两个地方就过了,具体修改的地方请参看程序. 知道最大值段和最小值段,然后修补一下就能过了.不是特别难的题目. #include <stdio.h> #include <string> #include <algorithm> using namespace std; c