【JZOJ3738】理想城市(city)

来源:互联网 发布:彻底清除kingroot软件 编辑:程序博客网 时间:2024/04/30 13:12

Description

这里写图片描述

Solution

把求的答案变一下,相当于一个非空的格可以往下走,答案就要加上经过这一步的路径总数。

那么,我们把横着连在一起的非空格缩成一个点(连通块),如果两个点上下有接触,就给两个点连边。这样构建的图一定是一棵树,那么我们考虑一条树边的贡献,就是它的两个端点分别连出去的点包含着非空格子数相乘。

竖着的同理。

Code

#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#define fo(i,j,k) for(int i=j;i<=k;i++)#define rep(i,x) for(int i=ls[x];i;i=nx[i])#define N 100010#define M 200010#define mod 3000007#define ll long long#define inf 2147483647#define mo 1000000000using namespace std;struct node{    int x,y;}b[N];int to[M],nx[M],ls[N],num=0;void link(int x,int y){    to[++num]=y,nx[num]=ls[x],ls[x]=num;}ll h[mod];int r=0,c=0;int o[mod];int g(int x,int y){    return (ll)(x-1)*c+y;}int f[N],fc[N],sz[N];int n;ll ans=0;int getf(int x){    return f[x]==x?x:f[x]=getf(f[x]);}int getfc(int x){    return fc[x]==x?x:fc[x]=getfc(fc[x]);}int hash(ll x){    int p=x%mod;    while(h[p] && h[p]!=x) p=(p+1)%mod;    return p;}void calc(int x,int t){    rep(i,x)    {        int v=to[i];        if(v==t) continue;        calc(v,x);        sz[x]+=sz[v];    }    rep(i,x)    {        int v=to[i];        if(v==t) continue;        ans=(ans+(ll)sz[v]*(n-sz[v]))%mo;    }}void work(int v1,int v2){    memset(ls,0,sizeof(ls));    num=0;    fo(i,1,n) f[i]=fc[i]=i,sz[i]=1;    fo(i,1,n)    {        int x=b[i].x,y=b[i].y;        if(x+v1>r || y+v2>c) continue;        int w1=hash(g(x,y)),w2=hash(g(x+v1,y+v2));        if(h[w2])        {            int fx=getf(o[w1]),fy=getf(o[w2]);            f[fy]=fx,sz[fx]+=sz[fy];            sz[fy]=0;        }    }    fo(i,1,n)    {        int x=b[i].x,y=b[i].y;        if(x+v2>r || y+v1>c) continue;        int w1=hash(g(x,y)),w2=hash(g(x+v2,y+v1));        if(h[w2])        {            int fx=getf(o[w1]),fy=getf(o[w2]);            int gx=getfc(fx),gy=getfc(fy);            if(gx!=gy) fc[gy]=gx,link(fx,fy),link(fy,fx);        }    }    calc(getf(1),0);}int main(){    freopen("city.in","r",stdin);    freopen("city.out","w",stdout);    scanf("%d",&n);    int p=inf,q=inf;    fo(i,1,n)    {        scanf("%d %d",&b[i].x,&b[i].y);        p=min(p,b[i].x),q=min(q,b[i].y);        r=max(r,b[i].x),c=max(c,b[i].y);    }    p--,q--;    r-=p,c-=q;    fo(i,1,n)    {        b[i].x-=p,b[i].y-=q;        ll t=g(b[i].x,b[i].y);        int wz=hash(t);        o[wz]=i,h[wz]=t;    }    work(0,1);    work(1,0);    printf("%lld",ans);}
2 0