[扫描线][倍增][dfs序][线段树] Jzoj P6276 树
Posted comfortable
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[扫描线][倍增][dfs序][线段树] Jzoj P6276 树相关的知识,希望对你有一定的参考价值。
题解
- 我们先把每个点在dfs上入队出队的时间给弄出来
- 然后可以转换为在平面上的n个矩阵
- 就可以用扫描线+线段树给过掉它了
代码
1 #include <cstdio> 2 #include <algorithm> 3 #define N 100010 4 #define ll long long 5 using namespace std; 6 struct edge ll to,from; e[N*2]; 7 struct Edge ll l,r,x,k; a[N*40]; 8 ll n,m,tot,cnt,num,ans,p=1,fa[17][N],head[N],d[N*4],tag[N*4],dfn[N][2],t[N*4]; 9 bool cmp(Edge a,Edge b) return a.x<b.x; 10 void insert(ll x,ll y) 11 12 e[++cnt].to=y,e[cnt].from=head[x],head[x]=cnt; 13 e[++cnt].to=x,e[cnt].from=head[y],head[y]=cnt; 14 15 void ins(ll x1,ll x2,ll y1,ll y2) a[++num]=(Edge)x1,x2,y1,1,a[++num]=(Edge)x1,x2,y2+1,-1; 16 void dfs(ll x) 17 18 dfn[x][0]=++tot; 19 for (ll i=head[x];i;i=e[i].from) if (!dfn[e[i].to][0]) dfs(e[i].to),fa[0][e[i].to]=x; 20 dfn[x][1]=tot; 21 22 void add(ll d,ll l,ll r,ll L,ll R,ll x) 23 24 if (l==L&&r==R) 25 26 tag[d]+=x; 27 if (l==r) t[d]=(tag[d]>0); else if (tag[d]) t[d]=r-l+1; else t[d]=t[d*2]+t[d*2+1]; 28 return; 29 30 ll mid=l+r>>1; 31 if (R<=mid) add(d*2,l,mid,L,R,x); else if (L>mid) add(d*2+1,mid+1,r,L,R,x); 32 else add(d*2,l,mid,L,mid,x),add(d*2+1,mid+1,r,mid+1,R,x); 33 if (tag[d]) t[d]=r-l+1; else t[d]=t[d*2]+t[d*2+1]; 34 35 int main() 36 37 freopen("tree.in","r",stdin),freopen("tree.out","w",stdout),scanf("%lld%lld",&n,&m); 38 for (ll i=1,x,y;i<n;i++) scanf("%lld%lld",&x,&y),insert(x,y); 39 dfs(1); 40 for (ll i=1;i<=16;i++) for (ll j=1;j<=n;j++) fa[i][j]=fa[i-1][fa[i-1][j]]; 41 for (ll i=1,x,y,x1,y1,x2,y2;i<=m;i++) 42 43 scanf("%lld%lld",&x,&y),x1=dfn[x][0],y1=dfn[y][0],x2=dfn[x][1],y2=dfn[y][1]; 44 if (x1>y1) swap(x,y),swap(x1,y1),swap(x2,y2); 45 if (x2<y1) ins(x1,x2,y1,y2),ins(y1,y2,x1,x2); 46 else 47 48 ll p=y; 49 for (ll j=16;j>=0;j--) if (dfn[fa[j][p]][0]>x1) p=fa[j][p]; 50 if (dfn[p][0]>1) ins(1,dfn[p][0]-1,y1,y2),ins(y1,y2,1,dfn[p][0]-1); 51 if (dfn[p][1]!=n) ins(dfn[p][1]+1,n,y1,y2),ins(y1,y2,dfn[p][1]+1,n); 52 53 54 sort(a+1,a+num+1,cmp); 55 for (ll i=1;i<=n;i++) 56 57 while (p<=num&&a[p].x==i) add(1,1,n,a[p].l,a[p].r,a[p].k),p++; 58 ans+=t[1]; 59 60 ans=(n*(n-1)-ans)/2,printf("%lld",ans); 61
以上是关于[扫描线][倍增][dfs序][线段树] Jzoj P6276 树的主要内容,如果未能解决你的问题,请参考以下文章