【THOI 2012】 水位

来源:互联网 发布:大数据分析预测 编辑:程序博客网 时间:2024/06/11 01:11

A1363.水位

思路题。

做这道题的时候如果思路清晰的话,就是一道简单的乘法原理+高精度题。

  • 按照原始高度升序排序

  • 最开始,所有点各自属于一个连通块

  • 按照高度顺序,从最低的开始合并连通块,假设当前处理到lr这个区间,他们的高度都是hl

    • 首先记住两点
      • 合并他们之前,每个连通块中每个点都是等高的
      • 合并他们的时候并不会影响到r之后的部分
    • 如何合并呢?
    • 我们枚举四个方向,如果被枚举的点y与当前点x不在一个连通块中,判断他们高度是否相同

      • 如果相同,直接把x的方案数乘上y点的方案数ans[y]
      • 如果不同,说明y这个连通块还可以整体抬高hxhy,此时ans[x]=(ans[y]+hxhy)
    • 于是这次合并之后,被合并过的连通块高度就都是hl

    • 然后继续上面的过程,知道剩下一个连通块

直接这样做是45分,加上高精度就AC了~

#include <iostream>#include <algorithm>#include <cmath>#include <cstring>#include <cstdio>#include <cstdlib>#define M 10005#define LL long long#define mod 10000using namespace std;int n,m;struct bign{    int l,x[5005];    bign operator = (int k)    {        x[1]=k;        l=1;        return *this;     }    void rebuild()    {        for (int i=1;i<=l;i++)        {            x[i+1]=x[i+1]+x[i]/mod;            x[i]%=mod;        }        while (x[l+1]>0)            l++,x[l+1]+=x[l]/mod,x[l]%=mod;    }    friend bign operator + (bign a,int k)    {        a.x[1]+=k;        a.rebuild();        return a;    }    friend bign operator * (bign a,bign b)    {        bign c;        c.l=a.l+b.l-1;        memset(c.x,0,sizeof(c.x));        for (int i=1;i<=a.l;i++)            for (int j=1;j<=b.l;j++)                c.x[i+j-1]+=a.x[i]*b.x[j]%mod,c.x[i+j]+=a.x[i]*b.x[j]/mod;        c.rebuild();        return c;    }    bign operator *= (bign k)    {        *this=*this * k;        return *this;    }}ans[M];struct data{    int x,y,h;}a[M];int fx[5][3],add[M],v[M],fa[M],dy[M];void Print(bign a){    printf("%d",a.x[a.l]);    for (int i=a.l-1;i;i--)        printf("%04d",a.x[i]);    printf("\n");}int C(int x,int y){    return (x-1)*n+y;}int read(){    int tmp=0;    char ch=getchar();    int fu=1;    for (;ch<'0'||ch>'9';ch=getchar())        if (ch=='-') fu=-1;    for (;ch>='0'&&ch<='9';ch=getchar())        tmp=tmp*10+ch-'0';    return tmp*fu;}bool cmp(data a,data b){    return a.h<b.h;}int Getfather(int x){    return x==fa[x]?x:fa[x]=Getfather(fa[x]);}int ok(int x,int y){    if (x>0&&y>0&&x<=n&&y<=n) return 1;    return 0;}int main(){    scanf("%d%d",&n,&m);    for (int i=1;i<=n;i++)        for (int j=1;j<=n;j++)            a[C(i,j)]=(data){i,j,read()},            fa[C(i,j)]=C(i,j),            ans[C(i,j)]=1;    sort(a+1,a+1+n*n,cmp);    for (int i=1;i<=n*n;i++)        dy[C(a[i].x,a[i].y)]=i;    a[n*n+1].h=m,a[0].h=a[1].h;    fx[0][1]=fx[1][1]=fx[2][2]=fx[3][2]=0;    fx[0][2]=fx[2][1]=1,fx[1][2]=fx[3][1]=-1;    int l=1,r=0;    while (l<=n*n)    {        r=l;        while (a[r].h==a[r+1].h&&r<n*n)            r++;        for (int i=l;i<=r;i++)        {            int c=C(a[i].x,a[i].y);            v[c]=1;            for (int k=0;k<4;k++)            {                int nx=a[i].x+fx[k][1],ny=a[i].y+fx[k][2];                int cc=C(nx,ny);                if (!ok(nx,ny)||!v[cc]) continue;                int f1=Getfather(cc);                if (f1!=c)                {                    if (a[dy[f1]].h==a[i].h)                        ans[c]*=ans[f1];                    else ans[c]*=(ans[f1]+(a[i].h-a[dy[f1]].h));                    fa[f1]=c;                }            }        }        l=r+1;    }    int x;    for (int i=1;i<=n*n;i++)        if (fa[i]==i)            x=i;    Print(ans[x]+(m-a[n*n].h));    return 0;}
3 0
原创粉丝点击