kop采矿

采矿(KOP)
    金矿的老师傅年底要退休了。经理为了奖赏他的尽职尽责的工作,决定送他一块长方形地。长度为S,宽度为W。老师傅可以自己选择这块地。显然其中包含的采金点越多越好。你的任务就是计算最多能得到多少个采金点。如果一个采金点的位置在长方形的边上,它也应当被计算在内。
任务:
    读入采金点的位置。计算最大的价值。
输入:
    文件KOP.IN的第一行是S和W,(1<=s,w<=10 000);他们分别平行于OX坐标和OY坐标,指明了地域的尺寸。接下来一行是整数n (1<=n<=15 000),表示采金点的总数。然后是n行,每行两个整数,给出了一个采金点的坐标。坐标范围是(-30 000<=x,y<=30 000)。
输出:
    一个整数,最多的采金点数。
样例输入
1 2
12
0 0
1 1
2 2
3 3
4 5
5 5
4 2
1 4
0 5
5 0
2 3
3 2
样例输出
4

做法:

    建立一颗平衡树,从左到右扫描

#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<cstdio>
#include<fstream>
#include<string>
#include<cstring>
using namespace std;
const int maxn=30010;
struct oo{ int v,sum,maxsum; };
struct o{ int x,y; };
oo a[maxn*4];
o b[15010];
int n,m,s,w,num(0),ans(0);

inline void init(){
    memset(a,0,sizeof(a));
    memset(b,0,sizeof(b));
    scanf("%d%d",&s,&w);
    scanf("%d",&n);
    for (int i=0; i<n; ++i){
        scanf("%d%d",&b[i].x,&b[i].y);
        b[i].x+=30000;
        b[i].y+=30000;
    }
}

inline bool cmp(const o c, const o d){ return c.x<d.x; }

inline int max(const int x, const int y){ return x>y?x:y; }

inline void build(int k){
    if (2*k<=60001) build(2*k);
    a[k].v=num++;
    if (2*k+1<=60001) build(2*k+1);
}

inline void insert_t(const int y, const int delta){
    int k=1;
    while (a[k].v!=y){
        if (y<a[k].v) k<<=1;
        else k=(k<<1)+1;
    }
    
    while (k>0){
       a[k].sum+=delta;
       if ((k<<1)+1<60001){ 
           a[k].maxsum=max(a[k<<1].maxsum,a[k].sum-a[(k<<1)+1].sum);  
           a[k].maxsum=max(a[k].maxsum,a[k].sum-a[(k<<1)+1].sum+a[(k<<1)+1].maxsum);
           k>>=1;
           continue;
       }
       if ((k<<1)<60001){
          a[k].sum=max(a[k<<1].maxsum,a[k].sum);
          k>>=1;
          continue;
       }
       a[k].maxsum=a[k].sum;
       k>>=1;
    }
}

inline void solve(){
     build(1);
     sort(b,b+n,cmp);
     int l=0, r=0; 
     insert_t(b[0].y,1); 
     if (b[0].y+w+1<60001) insert_t(b[0].y+w+1,-1);
     while (true){
         while (r<n-1&&b[r+1].x-b[l].x<=s){
              ++r;
              insert_t(b[r].y,1);
              if (b[r].y+w+1<60001) insert_t(b[r].y+w+1,-1);
         }
         if (a[1].maxsum>ans) ans=a[1].maxsum;
         int t=b[l].x;
         while (l<=n-1&&b[l].x==t){
               insert_t(b[l].y,-1);
               if (b[l].y+w+1<60001) insert_t(b[l].y+w+1,1);
               ++l;
         }
         
         if (r>=n-1||l>=n-1) break;
    }
    printf("%d\n",ans);
}

int main(){
    freopen("kop.in","r",stdin);
    freopen("kop.out","w",stdout);
    init();
    solve();
    fclose(stdin); fclose(stdout);
    return 0;
}

 

posted on 2012-12-09 16:04  yzcstc  阅读(147)  评论(0)    收藏  举报