【題目整理】

計算幾何

bzoj1038 [ZJOI2008]瞭望塔

半平面交。

#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const double INF=1e100;
const double eps=1e-10;
const int N=305;
struct point
{
    double x,y;
    point(){}
    point(double xx,double yy):x(xx),y(yy){}
    inline point operator +(const point other)const
    {
        return point(x+other.x,y+other.y);
    }
    inline point operator -(const point other)const
    {
        return point(x-other.x,y-other.y);
    }
    inline point operator *(const double other)const
    {
        return point(x*other,y*other);
    }
};
inline int dcmp(double a,double b)
{
    if(fabs(a-b)<eps) return 0;
    return a>b?1:-1;
}
inline double cross(point a,point b)
{
    return a.x*b.y-b.x*a.y;
}
inline double supercross(point a,point b,point c)
{
    return cross(point(b.x-a.x,b.y-a.y),point(c.x-b.x,c.y-b.y));
}
struct line
{
    point s,v;
    line(){}
    line(point ss,point vv):s(ss),v(vv){}
    inline bool operator <(const line other)const
    {
        double rate1=atan2(v.y,v.x),rate2=atan2(other.v.y,other.v.x);
        if(!dcmp(rate1,rate2)) return dcmp(supercross(s,s+v,other.s),0)==-1;
        else return rate1<rate2;
    }
};
inline point inter(line a,line b)
{
    point u=b.s-a.s;
    double rate=cross(u,b.v)/cross(a.v,b.v);
    return a.s+(a.v*rate);
}
inline bool onleft(line a,point p)
{
    return dcmp(supercross(a.s,a.s+a.v,p),0)>0;
}
inline double high(point a,point b,double p)
{
    return inter(line(a,b-a),line(point(p,0),point(0,1))).y;
}
struct halfinter
{
    line a[N],q[N];
    int n,h,t;
    point tmp[N];
    inline void solve()
    {
        sort(a+1,a+n+1);
        q[h=t=1]=a[1];
        for(int i=2;i<=n;i++)
        {
            if(!cross(a[i].v,a[i-1].v)) continue;
            while(h<t&&!onleft(a[i],inter(q[t-1],q[t]))) t--;
            while(h<t&&!onleft(a[i],inter(q[h],q[h+1]))) h++;
            q[++t]=a[i];
        }
        while(h+1<t&&!onleft(q[h],inter(q[t],q[t-1]))) t--;
        while(h+1<t&&!onleft(q[t],inter(q[h],q[h+1]))) h++;
        for(int i=h;i<t;i++)
          tmp[i]=inter(q[i],q[i+1]);
    }
}half;
int x[N],y[N];
int n;
double ans=INF;
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      scanf("%d",&x[i]);
    for(int i=1;i<=n;i++)
      scanf("%d",&y[i]);
    for(int i=1;i<n;i++)
      half.a[i]=line(point(x[i],y[i]),point(x[i+1]-x[i],y[i+1]-y[i]));
    half.n=n+1;
    half.a[n]=line(point(x[1],0),point(0,-1));
    half.a[n+1]=line(point(x[n],0),point(0,1));
    half.solve();
    for(int i=half.h,j=1;i<=half.t;i++)
    {
        while(dcmp(x[j],half.tmp[i].x)>0||dcmp(half.tmp[i].x,x[j+1])>0) j++;
        ans=min(ans,half.tmp[i].y-high(point(x[j],y[j]),point(x[j+1],y[j+1]),half.tmp[i].x));
    }
    for(int i=1,j=half.h;i<=n;i++)
    {
        while(dcmp(half.tmp[j].x,x[i])>0||dcmp(x[i],half.tmp[j+1].x)>0) j++;
        ans=min(ans,high(half.tmp[j],half.tmp[j+1],x[i])-y[i]);
    }
    printf("%.3lf",ans);
    return 0;
}

cogs896

凸包。

#include<cmath>
#include<cstdio>
#include<algorithm>
using namespace std;
const double eps=1e-10;
struct point
{
    double x,y;
    point(){}
    point(double xx,double yy):x(xx),y(yy){}
    inline point operator -(const point other)const
    {
        return point(x-other.x,y-other.y);
    }
    inline bool operator <(const point other)const
    {
        if(x==other.x) return y<other.y;
        return x<other.x;
    }
}a[10005],s[10005];
int n,top;
double ans;
inline int dcmp(double a,double b)
{
    if(fabs(a-b)<eps) return 0;
    return a>b?1:-1;
}
inline double cross(point a,point b)
{
    return a.x*b.y-a.y*b.x;
}
inline void solve()
{
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++)
    {
        while(top>1&&dcmp(cross(s[top]-s[top-1],a[i]-s[top-1]),0)<=0) top--;
        s[++top]=a[i];
    }
    int num=top;
    for(int i=n-1;i;i--)
    {
        while(top>num&&dcmp(cross(s[top]-s[top-1],a[i]-s[top-1]),0)<=0) top--;
        s[++top]=a[i];
    }
}
inline double sqr(double x){return x*x;}
int main()
{
    freopen("fc.in","r",stdin);
    freopen("fc.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      scanf("%lf%lf",&a[i].x,&a[i].y);
    solve();
    for(int i=1;i<top;i++)
      ans+=sqrt(sqr(s[i].x-s[i+1].x)+sqr(s[i].y-s[i+1].y));
    printf("%.2lf",ans);
    return 0;
}

線段樹

bzoj3165 [Heoi2013]Segment

李超線段樹。

#include<cstdio>
#include<iostream>
using namespace std;
#define pi pair<double,int>
#define mod1 39989
#define mod2 1000000000
const int N=1e5+10;
inline void swap(int &a,int &b){a^=b,b^=a,a^=b;}
struct line
{
    double k,b;
    int l,r,id;
    line(){}
    line(int x1,int y1,int x2,int y2,int ID)
    {
        if(x1>x2) swap(x1,x2),swap(y1,y2);
        if(x1==x2) k=0,b=max(y1,y2);
        else k=(double)(y2-y1)/(double)(x2-x1),b=y1-k*x1;
        l=x1,r=x2,id=ID;
    }
    inline double y(double x){return k*x+b;}
}t[N<<2];
int n,opt,x,y,z,w,ans,tot;
inline int point(line a,line b){return (b.b-a.b)/(a.k-b.k);}
void add(int l,int r,int now,line L)
{
    if(L.l<=l&&r<=L.r)
    {
        if(L.y(l)>t[now].y(l)&&L.y(r)>t[now].y(r)){t[now]=L;return;}
        if(L.y(l)<=t[now].y(l)&&L.y(r)<=t[now].y(r)) return;
        int pos=point(L,t[now]),mid=(l+r)>>1;
        if(pos<=mid)
          if(L.y(r)>t[now].y(r)) add(l,mid,now<<1,t[now]),t[now]=L;
          else add(l,mid,now<<1,L);
        else
          if(L.y(r)>t[now].y(r)) add(mid+1,r,now<<1|1,L);
          else add(mid+1,r,now<<1|1,t[now]),t[now]=L;
        return;
    }
    int mid=(l+r)>>1;
    if(L.l<=mid) add(l,mid,now<<1,L);
    if(L.r>mid) add(mid+1,r,now<<1|1,L);
}
pi ask(int p,int l,int r,int now)
{
    if(l==r) return pi(t[now].y(p),t[now].id);
    int mid=(l+r)>>1;pi ans;
    if(p<=mid) ans=max(pi(t[now].y(p),t[now].id),ask(p,l,mid,now<<1));
    else ans=max(pi(t[now].y(p),t[now].id),ask(p,mid+1,r,now<<1|1));
    return ans;
}
int main()
{
    scanf("%d",&n);
    while(n--)
    {
        scanf("%d",&opt);
        if(opt)
        {
            scanf("%d%d%d%d",&x,&y,&z,&w);
            x=(x+ans-1)%mod1+1,y=(y+ans-1)%mod2+1,
            z=(z+ans-1)%mod1+1,w=(w+ans-1)%mod2+1;
            add(1,40000,1,line(x,y,z,w,++tot));
        }
        else scanf("%d",&x),printf("%d\n",ans=ask((x+ans-1)%mod1+1,1,40000,1).second);
    }
    return 0;
}

bzoj1588 [HNOI2002]營業額統計

#include<cstdio>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=(1<<15)+10;
struct tree
{
    int maxn,minn;
}t[N<<2];
int a[N],tmp[N],s[N];
int n,ans,tot;
void build(int l,int r,int now)
{
    t[now].maxn=1e9,t[now].minn=0;
    if(l==r) return;
    int mid=(l+r)>>1;
    build(l,mid,now<<1);
    build(mid+1,r,now<<1|1);
}
inline void update(int now)
{
    t[now].maxn=min(t[now<<1].maxn,t[now<<1|1].maxn);
    t[now].minn=max(t[now<<1].minn,t[now<<1|1].minn);
}
void add(int p,int l,int r,int now)
{
    if(l==r)
    {
        t[now].maxn=t[now].minn=p;
        return;
    }
    int mid=(l+r)>>1;
    if(p<=mid) add(p,l,mid,now<<1);
    else add(p,mid+1,r,now<<1|1);
    update(now);
}
int askmax(int L,int R,int l,int r,int now)
{
    if(L<=l&&r<=R) return t[now].maxn;
    int mid=(l+r)>>1,ans=1e9;
    if(L<=mid) ans=askmax(L,R,l,mid,now<<1);
    if(R>mid) ans=min(ans,askmax(L,R,mid+1,r,now<<1|1));
    return ans;
}
int askmin(int L,int R,int l,int r,int now)
{
    if(L<=l&&r<=R) return t[now].minn;
    int mid=(l+r)>>1,ans=0;
    if(L<=mid) ans=askmin(L,R,l,mid,now<<1);
    if(R>mid) ans=max(ans,askmin(L,R,mid+1,r,now<<1|1));
    return ans;
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
      scanf("%d",&a[i]),s[i]=tmp[i]=a[i];
    sort(tmp+1,tmp+n+1);
    tot=unique(tmp+1,tmp+n+1)-tmp-1;
    for(int i=1;i<=n;i++)
      a[i]=lower_bound(tmp+1,tmp+tot+1,a[i])-tmp;
    ans=s[1];
    build(1,tot,1);
    add(a[1],1,tot,1);
    tmp[0]=1e9;
    for(int i=2;i<=n;i++)
    {
        int x=askmax(a[i],tot,1,tot,1),y=askmin(1,a[i],1,tot,1);
        if(x==1e9) ans+=abs(s[i]-tmp[y]);
        else if(y==1e9) ans+=abs(s[i]-tmp[x]);
        else ans+=min(abs(s[i]-tmp[x]),abs(s[i]-tmp[y]));
        add(a[i],1,tot,1);
    }
    printf("%d",ans);
    return 0;
}

網絡流

bzoj3144 [Hnoi2013]切糕

#include<queue>
#include<cstdio>
#include<cstring>
using namespace std;
#define pos(x,y,z) P*Q*(z-1)+(x-1)*Q+y
const int N=70005;
const int INF=1e9;
struct edge
{
    int nxt,to,remain;
}a[N<<2];
int head[N],dis[N];
int P,Q,R,D,num=1,ans,S,T,x;
queue<int>q;
inline void add(int x,int y,int z)
{
    a[++num].nxt=head[x],a[num].to=y,a[num].remain=z,head[x]=num;
    a[++num].nxt=head[y],a[num].to=x,head[y]=num;
}
inline bool bfs()
{
    memset(dis,0x3f,sizeof(dis));
    dis[S]=0;q.push(S);
    while(!q.empty())
    {
        int tmp=q.front();q.pop();
        for(int i=head[tmp];i;i=a[i].nxt)
          if(dis[a[i].to]>INF&&a[i].remain) dis[a[i].to]=dis[tmp]+1,q.push(a[i].to);
    }
    return dis[T]<INF;
}
int dfs(int now,int limit)
{
    if(now==T||!limit) return limit;
    int flow=0,f;
    for(int i=head[now];i;i=a[i].nxt)
      if(dis[a[i].to]==dis[now]+1&&a[i].remain&&(f=dfs(a[i].to,min(limit,a[i].remain))))
      {
        flow+=f,limit-=f,a[i].remain-=f,a[i^1].remain+=f;
        if(!limit) return flow;
      }
    dis[now]=-1;return flow;
}
inline int dinic(){int ans=0;while(bfs())ans+=dfs(S,INF);return ans;}
int main()
{
    scanf("%d%d%d%d",&P,&Q,&R,&D);
    S=P*Q*(R+1)+1,T=S+1;
    for(int i=1;i<=P;i++)
      for(int j=1;j<=Q;j++)
        add(S,pos(i,j,1),INF),add(pos(i,j,R+1),T,INF);
    for(int k=1;k<=R;k++)
      for(int i=1;i<=P;i++)
        for(int j=1;j<=Q;j++)
          scanf("%d",&x),add(pos(i,j,k),pos(i,j,k+1),x);
    for(int k=D+1;k<=R+1;k++)
      for(int i=1;i<=P;i++)
        for(int j=1;j<=Q;j++)
        {
            if(i!=P) add(pos(i,j,k),pos(i+1,j,k-D),INF);
            if(i!=1) add(pos(i,j,k),pos(i-1,j,k-D),INF);
            if(j!=Q) add(pos(i,j,k),pos(i,j+1,k-D),INF);
            if(j!=1) add(pos(i,j,k),pos(i,j-1,k-D),INF);
        }
    printf("%d",dinic());
    return 0;
}

bzoj2127 happiness

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
#define pos(x,y) (x-1)*m+y
const int N=30005;
const int INF=1e9;
struct edge
{
    int nxt,to,remain;
}a[N*15];
int head[N*15],dis[N*15];
int n,m,num=1,tot,x,S,T;
long long ans;
queue<int>q;
inline void add(int x,int y,int z)
{
    a[++num].nxt=head[x],a[num].to=y,a[num].remain=z,head[x]=num;
    a[++num].nxt=head[y],a[num].to=x,head[y]=num;
}
inline bool bfs()
{
    memset(dis,0x3f,sizeof(dis));
    dis[S]=0;q.push(S);
    while(!q.empty())
    {
        int tmp=q.front();q.pop();
        for(int i=head[tmp];i;i=a[i].nxt)
          if(dis[a[i].to]>INF&&a[i].remain) dis[a[i].to]=dis[tmp]+1,q.push(a[i].to);
    }
    return dis[T]<INF;
}
int dfs(int now,int limit)
{
    if(now==T||!limit) return limit;
    int flow=0,f;
    for(int i=head[now];i;i=a[i].nxt)
      if(dis[a[i].to]==dis[now]+1&&a[i].remain&&(f=dfs(a[i].to,min(limit,a[i].remain))))
      {
        flow+=f,limit-=f,a[i].remain-=f,a[i^1].remain+=f;
        if(!limit) return flow;
      }
    dis[now]=-1;return flow;
}
inline int dinic(){int ans=0;while(bfs())ans+=dfs(S,INF);return ans;}
int main()
{
    freopen("nt2011_happiness.in","r",stdin);
    freopen("nt2011_happiness.out","w",stdout);
    scanf("%d%d",&n,&m);
    //1~mn:學生 mn+1~mn+(n-1)*m+(m-1)*n:加點 
    S=5*m*n-((m+n)<<1)+1,T=S+1;
    for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
        scanf("%d",&x),add(S,pos(i,j),x),ans+=x;
    for(int i=1;i<=n;i++)
      for(int j=1;j<=m;j++)
        scanf("%d",&x),add(pos(i,j),T,x),ans+=x;
    tot=n*m;
    for(int i=1;i<n;i++)
      for(int j=1;j<=m;j++)
        scanf("%d",&x),add(S,++tot,x),add(tot,pos(i,j),INF),add(tot,pos(i+1,j),INF),ans+=x;
    for(int i=1;i<n;i++)
      for(int j=1;j<=m;j++)
        scanf("%d",&x),add(pos(i,j),++tot,INF),add(pos(i+1,j),tot,INF),add(tot,T,x),ans+=x;
    for(int i=1;i<=n;i++)
      for(int j=1;j<m;j++)
        scanf("%d",&x),add(S,++tot,x),add(tot,pos(i,j),INF),add(tot,pos(i,j+1),INF),ans+=x;
    for(int i=1;i<=n;i++)
      for(int j=1;j<m;j++)
        scanf("%d",&x),add(pos(i,j),++tot,INF),add(pos(i,j+1),tot,INF),add(tot,T,x),ans+=x;
    printf("%lld",ans-dinic());
    return 0;
}

bzoj0497 [NOI2006]最大獲利

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=55005;
const int INF=1e9;
struct edge
{
    int nxt,to,remain;
}a[500005];
int dis[N],head[N];
int n,m,x,y,z,num=1,S,T,ans;
queue<int>q;
inline void add(int x,int y,int z)
{
    a[++num].nxt=head[x],a[num].to=y,a[num].remain=z,head[x]=num;
    a[++num].nxt=head[y],a[num].to=x,head[y]=num;
}
inline bool bfs()
{
    memset(dis,0x3f,sizeof(dis));
    dis[S]=0;q.push(S);
    while(!q.empty())
    {
        int tmp=q.front();q.pop();
        for(int i=head[tmp];i;i=a[i].nxt)
          if(dis[a[i].to]>INF&&a[i].remain) dis[a[i].to]=dis[tmp]+1,q.push(a[i].to);
    }
    return dis[T]<INF;
}
int dfs(int now,int limit)
{
    if(now==T||!limit) return limit;
    int flow=0,f;
    for(int i=head[now];i;i=a[i].nxt)
      if(dis[a[i].to]==dis[now]+1&&a[i].remain&&(f=dfs(a[i].to,min(limit,a[i].remain))))
      {
        flow+=f,limit-=f,a[i].remain-=f,a[i^1].remain+=f;
        if(!limit) return flow;
      }
    dis[now]=-1;return flow;
}
inline int dinic(){int ans=0;while(bfs())ans+=dfs(S,INF);return ans;}
int main()
{
    freopen("profit.in","r",stdin);
    freopen("profit.out","w",stdout);
    scanf("%d%d",&n,&m);
    S=n+m+1,T=S+1;
    for(int i=1;i<=n;i++)
      scanf("%d",&x),add(m+i,T,x);
    for(int i=1;i<=m;i++)
      scanf("%d%d%d",&x,&y,&z),add(S,i,z),add(i,m+x,INF),add(i,m+y,INF),ans+=z;
    printf("%d",ans-dinic());
    return 0;
}
發佈了137 篇原創文章 · 獲贊 6 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章