线段树专辑 —— pku 2482 Stars in Your Window

http://poj.org/problem?id=2482

A了这题后,我就在想,是不是ACMER都找不到女朋友.....

这题看似很新颖,其实就是求线段树区间最值。所谓区间最值,其实就是和RMQ差不多,只不过RMQ是以点为单位,而这个是以区间为单位。

怎么扯到区间最值了呢?

因为每一颗星星,它都有一个亮度,假设这个星星现在正在最左边,那么它的亮度将会影响到向右W的范围。也就是说[star.x,star.x+W]这个区间都会因为这个亮度的影响而加上这个亮度值,最后求一个[x,x+W]的区间,并且该区间的亮度最大,这就是区间最值!方法和RMQ一样,只是不是更新到节点,而是更新到相应线段即可!

这里还要注意的几个地方

1、是这个题目要求恰好在窗户上的星星是不算数的,所以我们取区间[x,x+W]的时候,应该取[x,x+W-1]

2、必须离散化

3、注意高度上的要求,当最高的和最低的那颗星星的高度差等于或者超过H以后,我们就要减去最低的那颗星星亮度,因为窗户高度是有限的!

 

总的来说,就是不容易看出其数学模型,看出来后就很简单了

 

View Code
  1 #include<iostream>
2 #include<string>
3 #include<algorithm>
4 using namespace std;
5
6 struct node
7 {
8 int l;
9 int r;
10 __int64 add;
11 __int64 max_val;
12 };
13
14 node tree[100000];
15 int n,len;
16 __int64 H,W;
17 __int64 xx[20001];
18
19 struct star
20 {
21 __int64 x,y,c;
22 };
23
24 star num[10001];
25
26 int cmp(star a,star b)
27 {
28 return a.y<b.y;
29 }
30
31 int find(__int64 x)
32 {
33 int l=0,r=len,mid;
34 while(l<=r)
35 {
36 mid=(l+r)/2;
37 if(xx[mid]==x)
38 return mid;
39 if(xx[mid]<x)
40 l=mid+1;
41 else
42 r=mid-1;
43 }
44 return l;
45 }
46
47 void build(int i,int l,int r)
48 {
49 tree[i].l=l;
50 tree[i].r=r;
51 tree[i].add=0;
52 tree[i].max_val=0;
53 if(l==r)
54 return;
55 int mid=(l+r)/2;
56 build(2*i,l,mid);
57 build(2*i+1,mid+1,r);
58 }
59
60 void updata(int i,int l,int r,__int64 c)
61 {
62 if(tree[i].l>r || tree[i].r<l)
63 return;
64 if(tree[i].l>=l && tree[i].r<=r)
65 {
66 tree[i].add+=c;
67 tree[i].max_val+=c;
68 return;
69 }
70 if(tree[i].add)
71 {
72 tree[2*i].add+=tree[i].add;
73 tree[2*i+1].add+=tree[i].add;
74 tree[2*i].max_val+=tree[i].add;
75 tree[2*i+1].max_val+=tree[i].add;
76 tree[i].add=0;
77 }
78 updata(2*i,l,r,c);
79 updata(2*i+1,l,r,c);
80 tree[i].max_val=tree[2*i].max_val>tree[2*i+1].max_val?tree[2*i].max_val:tree[2*i+1].max_val;
81 }
82
83 int main()
84 {
85 int i,j,m,a,b;
86 freopen("in.txt","r",stdin);
87 while(scanf("%d%I64d%I64d",&n,&W,&H)!=EOF)
88 {
89 m=0;
90 for(i=0;i<n;i++)
91 {
92 scanf("%I64d%I64d%I64d",&num[i].x,&num[i].y,&num[i].c);
93 xx[m++]=num[i].x;
94 xx[m++]=num[i].x+W;
95 }
96 sort(xx,xx+m);
97 len=1;
98 for(i=1;i<m;i++)
99 {
100 if(xx[i-1]!=xx[i])
101 xx[len++]=xx[i];
102 }
103 len--;
104 build(1,0,len);
105 sort(num,num+n,cmp);
106 __int64 ans=0;
107 for(j=0,i=0;i<n;i++)
108 {
109 while(num[i].y-num[j].y>=H) //控制高度范围
110 {
111 a=find(num[j].x);
112 b=find(num[j].x+W)-1;
113 updata(1,a,b,-num[j].c);
114 j++;
115 }
116 a=find(num[i].x);
117 b=find(num[i].x+W)-1;
118 updata(1,a,b,num[i].c);
119 if(tree[1].max_val>ans)
120 ans=tree[1].max_val;
121 }
122 printf("%I64d\n",ans);
123 }
124 return 0;
125 }



posted @ 2011-11-14 10:50  Accept  阅读(259)  评论(0编辑  收藏  举报