[DP] BalkanOI 2016. Lefkaritika

题意大概是有求多少个不包含关键点的边长为整数的正方形。

转化一下就是求对于每个点 (x,y) ,以它为左上角的不包括关键点的正方形的边长最大值,令为 f(x,y)

答案就是 f(x,y)

考虑对于每条对角线上的点单独处理

设当前点为 (i,j) ,设 i 是最小的满足 (i,j) 为关键点且 i>i 的值, j 是最小的满足 (i,j) 为关键点且 j>j 的值(如果不存在就为无穷大),那么 f(i,j)=min{f(i+1,j+1)+1,jj,ii}

这样可以 O(n2) 搞,但实际上有用的点只有 O(B) 个,所以只要在这 O(B) 个点之间转移就好了

O(NBlogB)

实际上 log B 很小,所以是可以过的

也可以通过一些手段去掉这个log

还有一个问题就是求

k=1c1f(i+k,j+k)
,也就是两个有用的点之间的答案,这个东西可以转化成
k=1c1ck+f(i+c,j+c)=c(c1)2+(c1)f(i+c,j+c)
,这样就可以 O(1) 求啦

#include 
#include 
#include 
#include 

using namespace std;

typedef long long ll;

const int N=1010;

int l,w,n,x[N],y[N];
struct Pt{
    int x,y,d,r;
    Pt(int _x=0,int _y=0,int _d=0,int _r=0):x(_x),y(_y),d(_d),r(_r){}
    friend bool operator <(const Pt &a,const Pt &b){
        return a.xinline char nc(){
    static char buf[100000],*p1=buf,*p2=buf;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}

inline void rea(int &x){
    char c=nc(); x=0;
    for(;c>'9'||c<'0';c=nc());for(;c>='0'&&c<='9';x=x*10+c-'0',c=nc());
}

Pt p[N];
int id[N],f[N];
ll ans;

inline bool cmp(const int &a,const int &b){
    return x[a]int main(){
    rea(w); rea(l); rea(n);
    for(int i=1;i<=n;i++) 
        rea(x[i]),rea(y[i]),id[i]=i;
    sort(id+1,id+1+n,cmp);
    for(int L=-w+1;Lint t=0,cnt;
        for(int k=1;k<=n;k++){
            int i=id[k];
            if(y[i]==L+x[i]){
                p[++t]=Pt(x[i],y[i],x[i],y[i]);
            }
            else if(y[i]>L+x[i]){
                if(L+x[i]>0 && L+x[i]<=l)
                    p[++t]=Pt(x[i],L+x[i],w+1,y[i]);
            }
            else{
                if(y[i]-L>0 && y[i]-L<=w)
                    p[++t]=Pt(y[i]-L,y[i],x[i],l+1);    
            }
        }
        if(w+L<=l) p[++t]=Pt(w,w+L,w+1,w+L+1);
        else p[++t]=Pt(l-L,l,l-L+1,l+1);
        sort(p+1,p+1+t); cnt=t; t=1;
        for(int i=2;i<=cnt;i++)
            if(p[i].x==p[i-1].x) p[t].r=min(p[t].r,p[i].r),p[t].d=min(p[t].d,p[i].d);
            else p[++t]=p[i];
        f[t]=min(p[t].d-p[t].x,p[t].r-p[t].y)-1; p[0]=L<0?Pt(-L,0,-L,0):p[0]=Pt(0,L,0,L);
        for(int i=t-1;~i;i--){
            f[i]=min(min(p[i].r-p[i].y-1,p[i].d-p[i].x-1),f[i+1]+p[i+1].x-p[i].x);
            ans+=(p[i+1].x-p[i].x)*(p[i+1].x-p[i].x-1)/2+(p[i+1].x-p[i].x-1)*f[i+1];
            if(f[i]>0) ans+=f[i];
        }
    }
    cout<return 0;
}

你可能感兴趣的:(DP)