码迷,mamicode.com
首页 > 其他好文 > 详细

luogu3415 祭坛

时间:2018-02-13 22:14:36      阅读:134      评论:0      收藏:0      [点我收藏+]

标签:数组   names   sort   return   turn   i++   --   using   markdown   

先二分答案转化成判定问题。

考虑拿一根扫描线从 \(x=0\) 扫到 \(x=n\),每次移动扫描线更新每个位置它上面的点数和下面的点数,这样可以确定在当前的扫描线上哪些位置对于 \(y\) 轴方向是合法的。对于 \(x\) 轴方向合法的点应该处的范围可以直接算出来,树状数组维护。

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
int n, uu, vv, siz[100005], upp[100005], loo[100005], ans1, ans2, c[100005];
vector<int> vx[100005];
int lb(int x){
    return x&-x;
}
void add(int pos, int val){
    if(pos==0)  c[0]+=val,pos=n+n; 
    for(int i=pos; i<=n; i+=lb(i))  c[i] += val;
}
int query(int pos){
    int re=0;
    for(int i=pos; i; i-=lb(i)) re += c[i];
    return re+c[0];
}
bool check(int k){
    int num=0, l, r;
    for(int i=0; i<=n; i++) upp[i] = 0, loo[i] = siz[i], c[i]=0;
    for(int i=1; i<=n; i++){
        int qwqq=vx[i-1].size();
        for(int j=0; j<qwqq; j++){
            int t=vx[i-1][j];
            bool isok=(upp[t]>=k)&&(loo[t]>=k);
            upp[t]++;
            if(!isok && upp[t]>=k && loo[t]>=k) add(t, 1);
        }
        qwqq=vx[i].size();
        bool flag=qwqq>=2*k;
        if(flag)    l=vx[i][k-1]+1, r=vx[i][vx[i].size()-k]-1;
        for(int j=0; j<qwqq; j++){
            int t=vx[i][j];
            bool isok=(upp[t]>=k)&&(loo[t]>=k);
            loo[t]--;
            if(isok && !(upp[t]>=k && loo[t]>=k))   add(t, -1);
            if(isok && flag && t>=l && t<=r)    num--;
        }
        if(!flag || l>r)    continue;
        num += query(r) - query(l-1);
    }
    if(!num)    return false;
    ans1 = k; ans2 = num;
    return true;
}
int main(){
    cin>>n;
    for(int i=1; i<=n; i++){
        scanf("%d %d", &uu, &vv);
        vx[uu].push_back(vv);
        siz[vv]++; 
    } 
    for(int i=0; i<=n; i++) sort(vx[i].begin(), vx[i].end());
    int l=0, r=n, mid;
    while(l<=r){
        mid = (l + r) >> 1;
        if(check(mid))  l = mid + 1;
        else    r = mid - 1;
    }
    cout<<ans1<<endl<<ans2<<endl;
    return 0; 
}

luogu3415 祭坛

标签:数组   names   sort   return   turn   i++   --   using   markdown   

原文地址:https://www.cnblogs.com/poorpool/p/8447473.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!