poj 2482 Stars in Your Window 线段树

题意:平面上有n个星星,给出每个星星的位置和亮度 求一个W*H的矩形(不包括边界)使得矩形内的星星亮度之和最大。
 
思路:每个点(x,y,brightness) 存两个点(x,y,brightness)和(x,y+H,-brightness)
先离散化
从左到右两根间距为W的扫描线,左开右闭。依次把点加进线段树,下标是y,权值是brightness,题目所求的就是前i个点的和的最大值。
线段树存当前范围内的sum,maxsum
其中 maxsum[i]=max(maxsum[2*i],sum[2*i]+maxsum[2*i+1]);
ans=max(maxsum[i])
 
  1 #include<iostream>
2 #include<algorithm>
3 #include<cmath>
4 using namespace std;
5 #define MAXN 20002
6 struct node
7 {
8 int sum,maxsum;
9 int left,right;
10 };
11 struct star
12 {
13 long long x,y;
14 int degree;
15 int id;
16 };
17 node tree[MAXN*4];
18 star a[MAXN];
19 int home[MAXN];
20 int width,high;
21 int n;
22 void buildtree(int i)
23 {
24 tree[i].sum=tree[i].maxsum=0;
25 if(tree[i].left==tree[i].right)
26 return ;
27 int mid=(tree[i].left+tree[i].right)/2;
28 tree[2*i].left=tree[i].left; tree[2*i].right=mid;
29 tree[2*i+1].left=mid+1; tree[2*i+1].right=tree[i].right;
30 buildtree(2*i); buildtree(2*i+1);
31 }
32 bool cmp1(const star &x,const star &y)
33 {
34 if(x.y<y.y) return 1;
35 if(x.y==y.y&&x.x<y.x) return 1;
36 return 0;
37 }
38 bool cmp2(const star &x,const star &y)
39 {
40 return x.x<y.x;
41 }
42 void insert(int i,int x,int add)
43 {
44 if(tree[i].left==tree[i].right)
45 {
46 tree[i].maxsum=tree[i].sum=tree[i].sum+add;
47 return ;
48 }
49 int mid=(tree[i].left+tree[i].right)/2;
50 if(x<=mid) insert(2*i,x,add);
51 else insert(2*i+1,x,add);
52 tree[i].sum+=add;
53 tree[i].maxsum=max(tree[2*i].sum+tree[2*i+1].maxsum,tree[2*i].maxsum);
54 }
55 int main()
56 {
57 while(scanf("%d%d%d",&n,&width,&high)!=EOF)
58 {
59 int i,j,k;
60
61 int x,y,z;
62 for(i=1;i<=n;i++)
63 {
64 scanf("%lld%lld%d",&a[i].x,&a[i].y,&a[i].degree);
65 a[i].id=i; a[i+n].id=i+n;
66 a[i+n].x=a[i].x; a[i+n].y=a[i].y+high; a[i+n].degree=-a[i].degree;
67 }
68 n=2*n;
69 sort(a+1,a+n+1,cmp1);
70 j=0;
71 a[j].x=-1; a[j].y=-1;
72 for(i=1;i<=n;i++)
73 {
74 if(a[i].y==a[j].y&&a[i].x==a[j].x)
75 {
76 a[j].degree+=a[i].degree;
77 }
78 else
79 {
80 j++; a[j].x=a[i].x; a[j].y=a[i].y; a[j].id=a[i].id; a[j].degree=a[i].degree;
81 home[a[j].id]=j;
82 }
83 }
84 n=j;
85 tree[1].left=1; tree[1].right=n;
86 buildtree(1);
87 sort(a+1,a+n+1,cmp2);
88 long long l1,l2;
89 l1=a[1].x; l2=l1+width;
90 i=1; j=0;
91 int ans=0;
92 while(j<n)
93 {
94 if(a[i].x-l1<=a[j+1].x-l2)//必须是小于等于 左开右闭
95 {
96 l1=a[i].x;
97 while(a[i].x==l1)//每次一定要把线上的所有点都处理了
98 {
99 insert(1,home[a[i].id],-a[i].degree); i++;
100 }
101 l2=l1+width;
102 }
103 else
104 {
105 l2=a[j+1].x;
106 while(a[j+1].x==l2)
107 {
108 j++; insert(1,home[a[j].id],a[j].degree);
109 }
110 l1=l2-width;
111 }
112 if(tree[1].maxsum>ans) ans=tree[1].maxsum;
113 }
114 printf("%d\n",ans);
115 }
116 return 0;
117 }
  
原文地址:https://www.cnblogs.com/myoi/p/2343138.html