POI2001 金矿

问题描述

金矿的老师傅年底要退休了。经理为了奖赏他的尽职尽责的工作,决定在一块包含 n(n ≤ 15000) 个采金点的长方形土地中划出一块长度为 S ,宽度为 W 的区域奖励给他(1 ≤ s , w ≤ 10 000)。老师傅可以自己选择这块地的位置,显然其 中包含的采金点越多越好。你的任务就是计算最多能得到多少个采金点。如果一个采金点的位置在长方形的边上,它也应当被计算在内。

输入格式

输入文件的第一行有两个整数,中间用一个空格隔开,表示长方形土地的长和宽即s和w(1<=s,w<=10 000)。第二行有一个整数n(1<=n<=15 000),表示金矿数量。下面的n行与金矿相对应,每行两个整数x和y (-30 000<=x,y<=30 000),中间用一个空格隔开,表示金矿的坐标。

输出格式

输出文件只有一个整数,表示选择的最大金矿的数。

------------------------------------------------------------

正解=离散化+平衡树

  点比坐标小的多,离散之- =

  要求一个宽 s 长 w的且覆盖点最多的矩形

  维护一个宽度为  s 的带状区间 既满足宽度限制

  建立以y为关键字的平衡树维护之

  我们要求的既长度h的区间中的最大值

  将一个点x,y 拆成两个点

     x,y,权值为1

     x,y+h+1权值为-1

  维护一个这样的以y为第一关键字,权值为第二关键字的平衡树

  最大前缀和既长度h的区间中的最大值(Orz神差分前缀求和)

代码如下:

  1 #include<cstdio>
  2 #include<algorithm>
  3 #include<string>
  4 #include<cstring>
  5 #include<iostream>
  6 #include<cmath>
  7 #include<map>
  8 #include<queue>
  9 #define LL long long
 10 #define INF 999999999
 11 #define Min(num1,num2) if(num1>num2) num1=num2
 12 #define Max(num1,num2) if(num1<num2) num1=num2
 13 #define N 150000
 14 using namespace std ;
 15 struct Point {
 16     int x,y,neg,pos;
 17 }point[N];
 18 bool cmp(const Point &X,const Point &Y){
 19     return X.x<Y.x;
 20 }
 21 struct Tree{
 22     int l,r,f,v1,v2,sum,mmax;
 23 }a[N];
 24 int n,Root,Total,s,w,edge[N],top;
 25 int q[8000];
 26 void puit(int now){
 27     printf("No.%d L:%d R:%d V1:%d V2:%d Sum:%d Mmax:%d
",now,a[now].l,a[now].r,a[now].v1,a[now].v2,a[now].sum,a[now].mmax);
 28 }
 29 void update(int now){
 30 //    puit(now);
 31 //    printf("->
");
 32 //    puit(a[now].l); 
 33 //    puit(a[now].r);
 34 //    printf("-------------------------------
");
 35     a[now].sum=a[a[now].l].sum+a[a[now].r].sum+a[now].v2;
 36     a[now].mmax=max(a[a[now].l].mmax,a[a[now].l].sum+a[now].v2                 );
 37     a[now].mmax=max(a[now].mmax     ,a[a[now].l].sum+a[now].v2+a[a[now].r].mmax);
 38 }
 39 void put(int now){
 40     if(a[now].l) put(a[now].l);
 41     printf("%d ",a[now].v1);
 42     //printf("V1%d(V2%d)(Sum%d)(Mmax%d) ",a[now].v1,a[now].v2,a[now].sum,a[now].mmax);
 43     if(a[now].r) put(a[now].r);
 44 }
 45 void rig(int now){
 46     int f=a[now].f;
 47     a[now].f=a[f].f;
 48     if(a[a[f].f].l==f) a[a[f].f].l=now;
 49     if(a[a[f].f].r==f) a[a[f].f].r=now;
 50     a[f].f=now;
 51     a[f].l=a[now].r;
 52     a[a[now].r].f=f;
 53     a[now].r=f;
 54     update(f);
 55 }
 56 void lef(int now){
 57     int f=a[now].f;
 58     a[now].f=a[f].f;
 59     if(a[a[f].f].l==f) a[a[f].f].l=now;
 60     if(a[a[f].f].r==f) a[a[f].f].r=now;
 61     a[f].f=now;
 62     a[f].r=a[now].l;
 63     a[a[now].l].f=f;
 64     a[now].l=f;
 65     update(f);
 66 }
 67 void splay(int now,int F=0){
 68     while(a[now].f!=F){
 69         int f=a[now].f;
 70         int ff=a[f].f;
 71         if(ff==F)
 72             if(a[f].l==now) 
 73                 rig(now);
 74             else 
 75                 lef(now);
 76         else 
 77             if(a[ff].l==f)
 78                 if(a[f].l==now)
 79                     rig(f),rig(now);
 80                 else 
 81                     lef(now),rig(now);
 82             else
 83                 if(a[f].r==now)
 84                     lef(f),lef(now);
 85                 else
 86                     rig(now),lef(now);
 87     }
 88     update(now);
 89     if(!F) Root=now;
 90 }
 91 int insert(int v1,int v2){
 92     for(int  now=Root;;){
 93         q[++top]=now;
 94         if(v1<a[now].v1||(v1==a[now].v1&&v2<=a[now].v2))
 95              if(a[now].l) now=a[now].l;
 96              else{
 97                 a[now].l=++Total;
 98                 a[Total].v1=v1;
 99                 a[Total].v2=v2;
100                 a[Total].f=now;
101                  a[Total].sum=v2;
102                 a[Total].mmax=max(v2,0);
103                 break;
104              }
105         else 
106             if(a[now].r) now=a[now].r;
107             else{
108                 a[now].r=++Total;
109                 a[Total].v1=v1;
110                 a[Total].v2=v2;
111                 a[Total].f=now;
112                  a[Total].sum=v2;
113                  a[Total].mmax=max(v2,0);
114                  break;
115             } 
116     }
117     while(top) update(q[top--]);
118     splay(Total);
119 //    put(Root);
120 //    printf("
");
121     return Total;
122 }
123 int prev(int now){
124     splay(now);
125     now=a[now].l;
126     while(a[now].r) now=a[now].r;
127     return now;
128 }
129 int succ(int now){
130     splay(now);
131     now=a[now].r;
132     while(a[now].l) now=a[now].l;
133     return now;
134 }
135 void del(int now){
136     int start=prev(now);
137     int end=succ(now);
138     splay(start);
139     splay(end,Root);
140     a[a[Root].r].l=0;
141     update(a[Root].r);
142     update(Root);
143 }
144 void removeL(int now){
145     del(point[now].pos);
146     del(point[now].neg);
147 }
148 void removeR(int now){
149     point[now].pos=insert(point[now].y     ,1);
150     point[now].neg=insert(point[now].y+w+1,-1);
151 }
152 int main(){
153     scanf("%d%d%d",&s,&w,&n);
154     for(int i=1;i<=n;i++)
155         scanf("%d%d",&point[i].x,&point[i].y);
156     sort(point+1,point+1+n,cmp);
157     point[0].x=-INF;
158     int Maxedge=0;
159     for(int i=1;i<=n;i++)
160         if(point[i].x!=point[i-1].x)
161             edge[++Maxedge]=point[i].x;        
162     int L=1,now=0,R=1,ans=0;
163     Total=2;
164     Root=1;
165     a[1].v1=INF;
166     a[2].v1=-INF;
167     a[1].l=2;
168     a[2].f=1;
169     while(now<Maxedge){
170         ++now;
171         while(edge[now]-point[L].x>s&&L <=n) removeL(L),++L;
172         while(point[R].x==edge[now] &&R <=n) removeR(R),++R;
173         Max(ans,a[Root].mmax);
174         
175     }
176     printf("%d",ans);
177 }
View Code
原文地址:https://www.cnblogs.com/Blacko/p/3449193.html