kb-07专题线段树-04--离散化;

 1   /*
  2    poj2528
  3   线段树 好题,用到了离散化,二分定位,特殊的区间查寻方式;在下面的代码注释中有详细的解释;
  4  */
  5 #include<iostream>
  6 #include<cstdio>
  7 #include<cstring>
  8 #include<algorithm>
  9
 10 using namespace std;
 11 typedef struct
 12 {
 13     int l,r;
 14     int cnt;//记录该段有几张海报;
 15     int num;//记录该段下面是哪一张海报,0表示没有还海报或海报不唯一;
 16 }Node;
 17 int a[400010][2],n,dot[400010]={0},cou[400010]={0};
 18 Node tr[800010];
 19 void build(int rt,int l,int r)
 20 {
 21     tr[rt].l=l;
 22     tr[rt].r=r;
 23     tr[rt].cnt=0;
 24     tr[rt].num=0;
 25     if(l==r)
 26         return ;
 27     int mid=(l+r)/2;
 28     build(rt<<1,l,mid);
 29     build((rt<<1)|1,mid+1,r);
 30 }
 31 void Pushdown(int rt)
 32 {
 33     tr[rt<<1].cnt=1;
 34     tr[rt<<1|1].cnt=1;
 35     tr[rt<<1].num=tr[rt].num;
 36     tr[rt<<1|1].num=tr[rt].num;
 37     tr[rt].cnt=2;
 38     tr[rt].num=0;
 39 }
 40 void Update(int rt,int l,int r,int x)
 41 {
 42     if(tr[rt].l==l&&tr[rt].r==r)
 43     {
 44         tr[rt].cnt=1;
 45         tr[rt].num=x;
 46         return;
 47     }
 48     if(tr[rt].cnt==1)//当只有一张海报在这个区间的时候才需要pushdown所以可以判断一下;也可以写在pushdown函数里面,我觉得写在外面比较块;
 49         Pushdown(rt);
 50     if(l<=tr[rt<<1].r)
 51     {
 52         if(r<=tr[rt<<1].r)
 53             Update(rt<<1,l,r,x);
 54         else
 55             Update(rt<<1,l,tr[rt<<1].r,x);
 56     }
 57     if(r>=tr[rt<<1|1].l)
 58     {
 59         if(l>=tr[rt<<1|1].l)
 60             Update(rt<<1|1,l,r,x);
 61         else
 62             Update(rt<<1|1,tr[rt<<1|1].l,r,x);
 63     }
 64     if(tr[rt<<1].num==tr[rt<<1|1].num&&tr[rt<<1].cnt==1&&tr[rt<<1|1].cnt==1)//这以下是pushup的操作,写在这里了;
 65     {
 66         tr[rt].cnt=1;
 67         tr[rt].num=tr[rt<<1].num;
 68     }
 69     else
 70         tr[rt].cnt=2;
 71 }
 72 /*
 73    查询操作比较有趣,因为是查寻区间的海报种类,一个海报可能是首尾可见而中间不可见,所以没办法直接查得,
 74     所以在树的结点上记录的是海报的编号,这样就可以用一个辅助的数组记录哪一个在此次查询中出现过;、
 75     所以每次查询要全区间查询,然后再扫一遍数组;
 76     、每次扫到区间内容一质的时候就不用再扫了;
 77   */
 78 void Query(int rt)
 79 {
 80     if(tr[rt].cnt==1)
 81     {
 82         cou[tr[rt].num]=1;
 83         return ;
 84     }
 85     if(tr[rt].l==tr[rt].r)
 86         return ;
 87     if(tr[rt].cnt==0)
 88         return ;
 89     Query(rt<<1);
 90     Query(rt<<1|1);
 91 }
 92 int Erfen(int l,int r,int x)//用来确定该点在线段上的位置(离散后的位置);
 93 {
 94     while(l<=r)
 95     {
 96         int mid=(l+r)/2;
 97         if(x<dot[mid])
 98             r=mid-1;
 99         else
100             l=mid+1;
101     }
102     return r;
103 }
104 int main()
105 {
106     int T;
107     scanf("%d",&T);
108     while(T--)
109     {
110         memset(dot,0,sizeof(dot));
111         scanf("%d",&n);
112         int z=0;
113         for(int i=0;i<n;i++)
114         {
115             scanf("%d%d",&a[i][0],&a[i][1]);
116             dot[z++]=a[i][0];
117             dot[z++]=a[i][1];
118         }
119         sort(dot,dot+z);//将输入的数据排序后是离散化;因为数据范围比较大,因为只和区间有关,与区间内部的点没有关系,所以只要区间首尾就好;
120         int t=1;
121         for(int i=1;i<z;i++)
122         {
123             if(dot[i]!=dot[i-1])
124                 dot[t++]=dot[i];
125         }
126         for(int i=t-1;i>0;i--)
127         {
128             if(dot[i]-dot[i-1]>1)
129                 dot[t++]=dot[i-1]+1;
130         }
131         sort(dot,dot+t);
132         for(int i=t;i>0;i--)
133             dot[i]=dot[i-1];
134         memset(tr,0,sizeof(tr));
135         build(1,1,t+5);
136         for(int i=1;i<=n;i++)
137         {
138             int temp1=Erfen(1,t,a[i-1][0]);
139             int temp2=Erfen(1,t,a[i-1][1]);
140             Update(1,temp1,temp2,i);
141         }
142         memset(cou,0,sizeof(cou));
143         Query(1);
144         int ans=0;
145         for(int i=1;i<=n;i++)
146             if(cou[i]==1)
147                 ans++;
148         printf("%d\n",ans);
149     }
150     return 0;
151  }
时间: 2024-10-05 11:57:58

kb-07专题线段树-04--离散化;的相关文章

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

POJ 3277 City Horizon(线段树+扫描线+离散化)

题目地址:POJ 3277 水题..稍微处理一下然后用求面积并的方法求即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <

hdu1542 Atlantis (线段树+扫描线+离散化)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 9032    Accepted Submission(s): 3873 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

Mayor&#39;s posters---poj2528线段树、离散化

题目链接:http://poj.org/problem?id=2528 题意:有n张海报要贴,每张需要用的区间为L到R,后面的可以贴在之前的上面,就是吧之前的挡住,求最后我们能看到几张海报: 我们可以倒着处理,因为最后贴的我们是能看到的:如果区间被贴过了result不加,没有贴过就+1并标记一下: 由于数据范围太大所以用线段树 #include<stdio.h> #include<math.h> #include<string.h> #include<algori

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

POJ2528Mayor&#39;s posters 线段树,离散化技巧

题意:一个坐标轴从1~1e7,每次覆盖一个区间(li,ri),问最后可见区间有多少个(没有被其他区间挡住的) 线段树,按倒序考虑,贴上的地方记为1,每次看(li,ri)这个区间是否全是1,全是1就说明在它后面贴的把它给挡住了,否则该海报可见. 然后就愉快的MLE了.... 再看看数据范围,离散化如下,比如如果海报的左右端点如下 那图中橙色的一块的大小其实对结果没有影响,可以把他们都缩为1 最后离散化结果如下图: 代码: 1 #include <algorithm> 2 #include <

HDU 1542 Atlantis (线段树 + 扫描线 + 离散化)

Atlantis Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 8998    Accepted Submission(s): 3856 Problem Description There are several ancient Greek texts that contain descriptions of the fabled i

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

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

HDU 1255 覆盖的面积 (线段树+扫描线+离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1255 题意很清楚,就是让你求矩阵之间叠加层数大于1的矩形块的面积和. 因为n只有1000,所以我离散化一下,数据大小就缩小了,那么之后只需要线段树单点更新就好了. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <map> 5 #include <algor