【JZOJ100019】A
来源:互联网 发布:长春前锦网络信息公司 编辑:程序博客网 时间:2024/06/03 16:43
Description
Solution
结论1:
结论2:给一棵树前序遍历,一颗子树的在dfs序上是连续的。
然后我们枚举起点,枚举不能通过的点,那么有些点对是不合法的。
有以下两种情况:
第一种(如左图)是两个点互不包含:a节点所在dfs序上所包含的区间为
第二种(如右图)是包含的情况,那么k*a点为一个区间
我们可以发现,除去b点(在a,b路径上且是a的儿子)的子树,那么剩余的就是不能通过的,也就是两个区间:
于是构造出所有矩形,求矩形覆盖的面积就是不合法路径的方案,用总数减去即可。
求矩形覆盖面积可以用扫描线+线段树。
Solution
#include<cstdio>#include<cstdlib>#include<cstring>#include<algorithm>#include<cmath>#define fo(i,j,k) for(int i=j;i<=k;i++)#define fd(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 ll long longusing namespace std;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;}int dep[N],fa[N][18],L[N],R[N],dfn=0;int lg[N];void pre(int x){ L[x]=++dfn; rep(i,x) { int v=to[i]; if(v==fa[x][0]) continue; fa[v][0]=x; dep[v]=dep[x]+1; pre(v); } R[x]=dfn;}int jump(int u,int v){ if(dep[u]<dep[v]) swap(u,v); fd(i,lg[dep[u]-dep[v]+1],0) if(dep[fa[u][i]]>dep[v]) u=fa[u][i]; return u;}struct node{ int x,l,r; int w;}b[N*50];struct tree{ int x,lz;}tr[N*8];int tot=0;void putin(int x,int y,int p,int q){ if(x>p) swap(x,p); if(y>q) swap(y,q); if(p<y) swap(x,y),swap(p,q); b[++tot].x=x,b[tot].l=y,b[tot].r=q,b[tot].w=1; b[++tot].x=p+1,b[tot].l=y,b[tot].r=q,b[tot].w=-1;}bool cmp(node x,node y){ return x.x<y.x;}void add(int v,int l,int r,int x,int y,int p){ if(l==x && r==y) { tr[v].lz+=p; if(tr[v].lz) tr[v].x=r-l+1; else tr[v].x=tr[v*2].x+tr[v*2+1].x; return; } int mid=(l+r)/2; if(y<=mid) add(v*2,l,mid,x,y,p); else if(x>mid) add(v*2+1,mid+1,r,x,y,p); else add(v*2,l,mid,x,mid,p),add(v*2+1,mid+1,r,mid+1,y,p); if(tr[v].lz) tr[v].x=r-l+1; else tr[v].x=tr[v*2].x+tr[v*2+1].x;}int main(){ freopen("a.in","r",stdin); freopen("a.out","w",stdout); int n; scanf("%d",&n); fo(i,2,n) { int x,y; scanf("%d %d",&x,&y); link(x,y),link(y,x); lg[i]=log2(i); } dep[1]=1; pre(1); fo(j,1,lg[n]) fo(i,1,n) fa[i][j]=fa[fa[i][j-1]][j-1]; fo(i,1,n) fo(j,2,n/i) { int p=i,q=i*j; if(L[p]>L[q]) swap(p,q); if(L[p]<=L[q] && R[q]<=R[p]) { int qson=jump(p,q); int p1=p,q1=q; if(L[qson]>1) putin(L[q],1,R[q],L[qson]-1); if(R[qson]<n) putin(L[q],R[qson]+1,R[q],n); } else putin(L[p],L[q],R[p],R[q]); } sort(b+1,b+tot+1,cmp); ll ans=n*1ll*(n-1)/2; int c=0; fo(i,1,n) { while(b[c+1].x==i && c<tot) c++,add(1,1,n,b[c].l,b[c].r,b[c].w); ans-=tr[1].x; } printf("%lld",ans);}
阅读全文
1 0
- [JZOJ100019]A
- 【JZOJ100019】A
- 【JZOJ100019】A 题解
- [JZOJ100019] 【NOI2017模拟6.26】A
- a
- a
- a
- a
- a
- a
- a
- a
- a
- a
- a
- a
- a
- A
- android长按事件
- Google VR for android
- 九度OJ 1040:Prime Number
- Spring.xml配置
- C# 如何新建和发送带附件的邮件
- 【JZOJ100019】A
- cocoapods报错问题You need at least git version 1.8.5 to use CocoaPods
- logcat的基本使用
- SpringMVC.xml配置
- sql语句 用户一天的数据,取最大的一条,再统计
- linux 下采用 CMake 方式开发php扩展(二)
- 下拉框筛选控件
- web.xml配置
- Redis scan