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\n",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("->\n"); 32 // puit(a[now].l); 33 // puit(a[now].r); 34 // printf("-------------------------------\n"); 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("\n"); 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 }