码迷,mamicode.com
首页 > 其他好文 > 详细

hud -5124-lines(线段树)

时间:2015-11-08 14:51:23      阅读:188      评论:0      收藏:0      [点我收藏+]

标签:

题目的意思是求重合层数最多的段(把点也看成段)。

给的数据范围为N<1e5;

ai<1e9;

有于N只有1e5;那么离散化一下可以将ai的范围映射到1e5,而不改变原端点的相对大小。

接下来用线段树来做就行了,要用lazy操作,到最后再把所有的值放下,然后比较每个点的大小,最大的就为重合最多的。

线段树复杂度为N*log(N);

 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<string.h>
 5 #include<stdlib.h>
 6 #include<math.h>
 7 #include<map>
 8 void local(int l,int r,int k);
 9 void add(int l,int r,int k,int uu,int ww);
10 typedef long long ll;
11 typedef struct pp
12 {
13     int x;
14     int y;
15 } ss;
16 int tree[4*100005];//线段树数组
17 int su[100005*2];
18 ss dd[100005];//结构体存段
19 int N;
20 using namespace std;
21 int main(void)
22 {
23     int i,j,k,num;
24     scanf("%d",&k);
25     while(k--)
26     {
27         N=0;
28         fill(tree, tree+4*100005,0);
29         scanf("%d",&num);
30         int z=0;
31         map<int,int>my;//映射
32         for(i=0; i<num; i++)
33         {
34             scanf("%d %d",&dd[i].x,&dd[i].y);
35             su[z]=dd[i].x;
36             z++;
37             su[z]=dd[i].y;
38             z++;
39         }
40         sort(su,su+z);
41         j=1;
42         for(i=0; i<z; i++)
43         {
44             if(my[su[i]]==0)
45             {
46                 my[su[i]]=j;
47                 j++;
48             }
49 
50         }//离散化
51         for(i=0; i<num; i++)
52         {
53             int x=dd[i].x=my[dd[i].x];
54             int y=dd[i].y=my[dd[i].y];
55             add(x,y,0,1,j-1);//线段树加段更新
56         }
57         local(1,j-1,0);//最后下放查询
58         printf("%d\n",N);
59     }
60     return 0;
61 
62 }
63 void add(int l,int r,int k,int uu,int ww)//建树更新
64 {
65     if(l>ww||r<uu)
66     {
67         return ;
68     }
69     else if(l<=uu&&r>=ww)
70     {
71         tree[k]+=1;
72     }
73     else
74     {
75         add(l,r,2*k+1,uu,(uu+ww)/2);
76         add(l,r,2*k+2,(uu+ww)/2+1,ww);
77     }
78 }
79 void local(int l,int r,int k)//下放查询
80 {
81     if(l==r)
82     {
83         if(N<tree[k])
84         {
85             N=tree[k];
86         }
87         return ;
88     }
89     else
90     {
91         tree[2*k+1]+=tree[k];
92         tree[2*k+2]+=tree[k];
93         local(l,(l+r)/2,2*k+1);
94         local((l+r)/2+1,r,2*k+2);
95 
96     }
97 }

[title]1002 lines[/title] 我们可以将一条线段[x_i,y_i][x?i??,y?i??]分为两个端点x_ix?i??和(yi)+1(yi)+1,在x_ix?i??时该点会新加入一条线段,同样的,在(y_i)+1(y?i??)+1时该点会减少一条线段,因此对于2n个端点进行排序,

x_ix?i??为价值1,y_iy?i??为价值-1,问题转化成了最大区间和,因为1一定在-1之前,因此问题变成最大前缀和,我们寻找最大值就是答案

技术分享
 1 #include<stdio.h>
 2 #include<algorithm>
 3 #include<iostream>
 4 #include<stdlib.h>
 5 #include<string.h>
 6 #include<math.h>
 7 #include<map>
 8 int f(const void*p,const void*q);
 9 typedef long long ll;
10 typedef struct pp
11 {
12     int x;
13     int y;
14 } ss;
15 using namespace std;
16 ss a[100005*2];
17 int main(void)
18 {
19     int i,j,k,p,q,s,l;
20     scanf("%d",&k);
21     while(k--)
22     {
23         scanf("%d",&p);
24         int uu=0;
25         for(i=0; i<p; i++)
26         {
27             scanf("%d",&s);
28             a[uu].x=s;
29             a[uu].y=1;
30             uu++;
31             scanf("%d",&l);
32             a[uu].x=l;
33             a[uu].y=0;
34             uu++;
35         }
36         qsort(a,uu,sizeof(ss),f);
37         ll sum=0;
38         ll dd=0;
39         for(i=0; i<uu; i++)
40         {
41             if(a[i].y==1)
42             {
43                 sum++;
44                 if(sum>dd)
45                 {
46                     dd=sum;
47                 }
48             }
49             else sum--;
50         }
51         printf("%lld\n",dd);
52 
53     }
54     return 0;
55 }
56 int f(const void*p,const void*q)
57 {
58     ss*w=(ss*)p;
59     ss*r=(ss*)q;
60     if(w->x==r->x)
61     {
62         return r->y-w->y;
63     }
64     return w->x-r->x;
65 }
View Code

 

hud -5124-lines(线段树)

标签:

原文地址:http://www.cnblogs.com/zzuli2sjy/p/4947038.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!