[DP] BalkanOI 2016. Lefkaritika

来源:互联网 发布:cicret软件 编辑:程序博客网 时间:2024/06/02 00:12

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

转化一下就是求对于每个点 (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 <cstdio>#include <iostream>#include <algorithm>#include <vector>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.x<b.x;    }};inline 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]<x[b];}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;L<l;L++){        int 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<<ans<<endl;    return 0;}
原创粉丝点击