[树形dp] Jzoj P3738 理想城市

Description



 

题解

  • 我们将横纵的贡献分开来考虑,想办法让图变成一棵树,这样就会好做很多
  • 先考虑横向的贡献,那么我们可以把纵向一段连续的区块给缩成一个点
  • 向左右相邻的连一条边权为1的树边,然后构出一棵树后
  • 考虑如果求出每一条边的贡献,显然一条边的贡献就是将这棵树分成两棵树,两棵树上两两点对应
  • 所以贡献就是size[x]*(n-size[x])
  • 对于纵向的话,将横纵坐标交换一下再做就ok了

 

代码

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 #include <algorithm> 
 5 #define ll long long
 6 using namespace std;
 7 const ll mo=1e9,M=1e5+10,N=3123457;
 8 ll n,cnt,mnx=mo,mny=mo,head[M],p[M],ans,hs[N],bz[N],size[M];
 9 struct node {ll x,y;}a[M];
10 struct edge {ll to,from;}e[M];
11 bool cmp(node a,node b) { return a.x==b.x?a.y>b.y:a.x<b.x; }
12 ll pd(ll x) 
13 { 
14     ll y=x%N;
15     for (;hs[y]!=0&&hs[y]!=x;y=(y+1)%N);
16     hs[y]=x; return y;
17 }
18 void insert(ll x,ll y)
19 {
20     if (e[head[x]].to==y) return;
21     e[++cnt].to=y,e[cnt].from=head[x],head[x]=cnt;
22     e[++cnt].to=x,e[cnt].from=head[y],head[y]=cnt;
23 }
24 void build()
25 {
26     sort(a+1,a+n+1,cmp);
27     for (ll i=1;i<=n;i++) bz[pd(a[i].x*n+a[i].y)]=i;
28     for (ll i=n;i>=1;i--)
29     {
30         ll x=a[i].x,y=a[i].y;
31         if (p[i]==0)
32         {
33             p[i]=i,size[i]=1;
34             for (ll j=i-1;j>=1;j--) if (a[j].y==a[j+1].y+1) p[j]=i,size[i]++; else break;
35         }
36         ll q=pd((x+1)*n+y); if (bz[q]) insert(p[i],p[bz[q]]);
37     }
38 }
39 void dfs(ll x,ll fa)
40 {
41     for (ll i=head[x];i;i=e[i].from) if (e[i].to!=fa) dfs(e[i].to,x),size[x]+=size[e[i].to];
42     for (ll i=head[x];i;i=e[i].from) if (e[i].to!=fa) ans=(ans+size[e[i].to]*(n-size[e[i].to])%mo)%mo;
43 }
44 int main()
45 {
46     freopen("city.in","r",stdin),freopen("city.out","w",stdout),scanf("%lld",&n);
47     for (ll i=1;i<=n;i++) scanf("%lld%lld",&a[i].x,&a[i].y),mnx=min(mnx,a[i].x),mny=min(mny,a[i].y);
48     for (ll i=1;i<=n;i++) a[i].x-=mnx-1,a[i].y-=mny-1;
49     build(),dfs(p[1],0);
50     for (ll i=1;i<=n;i++) swap(a[i].x,a[i].y);
51     cnt=0; for (ll i=1;i<M;i++) head[i]=size[i]=p[i]=0;
52     for (ll i=1;i<N;i++) hs[i]=bz[i]=0;
53     build(),dfs(p[1],0),printf("%lld",ans);
54 }

 

posted @ 2019-08-10 19:59  BEYang_Z  阅读(177)  评论(0编辑  收藏  举报