浅谈树分治:https://www.cnblogs.com/AKMer/p/10014803.html

题目传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3648

基环树分治,结合了点分和边分的思想。

先随便拆掉环上一条边,我们先称它为基边,把它当做树做一遍,跟Free Tour II差不多。

剩下的问题就是如何统计经过基边的路径条数了。我们将基边连着的两个点分别成为\(st\)和\(ed\),\(st\)的顺时针方向是\(ed\),\(ed\)的逆时针方向是\(st\)。直接跟边分一样去分别处理\(st\)和\(ed\)能延伸出去的路径长度不行,因为这样会在环上产生交集然后统计不合法的路径。所以我们枚举基边以外的边去断开再统计答案,就可以保证统计出来的答案不重不漏了。

然后因为只要做一遍,所以大力树状数组也没关系。

时间复杂度:\(O(nlogn)\)

空间复杂度:\(O(n)\)

代码如下:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
#define low(i) ((i)&(-(i))) const int maxn=1e5+5; ll ans;
bool vis[maxn],bo;
int n,m,limit,tot=1,id,mx,rt,N;
int now[maxn],pre[maxn*2],son[maxn*2];
int siz[maxn],f[maxn],g[maxn],depest[maxn],V[maxn]; int read() {
int x=0,f=1;char ch=getchar();
for(;ch<'0'||ch>'9';ch=getchar())if(ch=='-')f=-1;
for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+ch-'0';
return x*f;
} void add(int a,int b) {
pre[++tot]=now[a];
now[a]=tot,son[tot]=b;
} struct TreeArray {
int c[maxn]; void change(int pos,int v) {
if(pos==n-13)mx++;
for(int i=pos;i<=n;i+=low(i))
c[i]+=v;
} int query(int pos) {
int res=0;
for(int i=pos;i;i-=low(i))
res+=c[i];
return res;
}
}T; struct ring {
int node1,node2;
int dis[maxn],nxt[maxn],lst[maxn]; bool find_ring(int fa,int u) {
vis[u]=1;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(v!=fa) {
if(vis[v])id=p>>1,node1=v,node2=u;
if(vis[v]||find_ring(u,v)) {
nxt[u]=v,lst[v]=u;
return 1;
}
}
return 0;
} void dfs(int fa,int u,int num) {
if(num==1)dis[u]=dis[fa]+1;
T.change(n-dis[u]+1,num);
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v]&&v!=fa)dfs(u,v,num);
} void query(int fa,int u) {
dis[u]=dis[fa]+1,ans+=T.query(n-(max(1,limit-dis[u]))+1);
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v]&&v!=fa)query(u,v);
} void work() {
lst[node1]=node2;
memset(vis,0,sizeof(vis));
int st=son[id<<1],ed=son[id<<1|1];
if(nxt[st]==ed)swap(st,ed);
int pos=st;vis[ed]=1;
while(pos!=ed)vis[pos]=1,pos=nxt[pos];
dis[ed]=0,pos=st;mx=0;
while(pos!=ed)dfs(lst[pos],pos,1),pos=nxt[pos];dfs(lst[ed],ed,1);
pos=ed;dis[st]=0;
while(pos!=st)dfs(nxt[pos],pos,-1),query(nxt[pos],pos),pos=lst[pos];
}
}R; void find_rt(int fa,int u) {
int res=0;siz[u]=1;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v]&&(p>>1)!=id&&v!=fa)
find_rt(u,v),siz[u]+=siz[v],res=max(res,siz[v]);
res=max(res,N-siz[u]);
if(res<mx)mx=res,rt=u;
} void dfs(int fa,int u,int dep) {
mx=max(mx,dep),siz[u]=1;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v]&&(p>>1)!=id&&v!=fa)
dfs(u,v,dep+1),siz[u]+=siz[v];
} bool cmp(int a,int b) {
return depest[a]<depest[b];
} void query(int fa,int u,int dep) {
ans+=f[max(1,limit-dep)];
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v]&&v!=fa&&(p>>1)!=id)query(u,v,dep+1);
} void solve(int fa,int u,int dep) {
g[dep]++;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v]&&v!=fa&&(p>>1)!=id)solve(u,v,dep+1);
} void work(int u,int size) {
N=size,mx=rt=n+1,find_rt(0,u),u=rt,vis[u]=1,tot=0;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v]&&(p>>1)!=id) {
V[++tot]=v,mx=0;
dfs(u,v,2),depest[v]=mx;
}
sort(V+1,V+tot+1,cmp);
for(int i=1;i<=tot;i++) {
query(u,V[i],1);
solve(u,V[i],2);
for(int j=depest[V[i]];j;j--)
g[j]+=g[j+1],f[j]+=g[j];
for(int j=1;j<=depest[V[i]];j++)g[j]=0;
}
ans+=f[limit];
for(int i=1;i<=depest[V[tot]];i++)f[i]=g[i]=0;
for(int p=now[u],v=son[p];p;p=pre[p],v=son[p])
if(!vis[v]&&(p>>1)!=id)work(v,siz[v]);
} int main() {
n=read(),m=read(),limit=read();
for(int i=1;i<=m;i++) {
int a=read(),b=read();
add(a,b),add(b,a);
}
if(m==n)R.find_ring(0,1);
memset(vis,0,sizeof(vis));
work(1,n);
if(m==n)R.work();
printf("%lld\n",ans);
return 0;
}

BZOJ3648:寝室管理的更多相关文章

  1. BZOJ3648 寝室管理 【点分治 + 环套树】

    3648: 寝室管理 Time Limit: 40 Sec  Memory Limit: 512 MB Submit: 366  Solved: 152 [Submit][Status][Discus ...

  2. bzoj3648: 寝室管理(环套树+点分治)

    好题..写了两个半小时hh,省选的时候要一个半小时内调出这种题目还真是难= = 题目大意是给一棵树或环套树,求点距大于等于K的点对数 这里的树状数组做了一点变换.不是向上更新和向下求和,而是反过来,所 ...

  3. BZOJ3648 : 寝室管理

    求环套外向树上节点数不小于K的路径数. 首先树的话直接点分治+树状数组$O(n\log^2n)$搞定 环套树的话,先删掉多余的边(a,b) 然后变成了一棵树,直接点分治 然后在树上找到a到b的路径,将 ...

  4. 【BZOJ3648】寝室管理 树分治

    [BZOJ3648]寝室管理 Description T64有一个好朋友,叫T128.T128是寄宿生,并且最近被老师叫过去当宿管了.宿管可不是一件很好做的工作,碰巧T128有一个工作上的问题想请T6 ...

  5. 【BZOJ-3648】寝室管理 环套树 + 树状数组 + 点分治

    3648: 寝室管理 Time Limit: 40 Sec  Memory Limit: 512 MBSubmit: 239  Solved: 106[Submit][Status][Discuss] ...

  6. BZOJ 3648: 寝室管理( 点分治 + 树状数组 )

    1棵树的话, 点分治+你喜欢的数据结构(树状数组/线段树/平衡树)就可以秒掉, O(N log^2 N). 假如是环套树, 先去掉环上1条边, 然后O(N log^2 N)处理树(同上); 然后再O( ...

  7. BZOJ 3648 寝室管理

    [题解] GDOI2016 Day2T3 如果给出的数据是一棵树那么皆大欢喜直接点分治就好了,用树状数组维护大于x的数的个数.如果是一棵基环树,我们先断掉环上的一条边,然后跑点分治:再加上经过这条边的 ...

  8. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  9. 第五次作业——Alpha项目测试

    第五次作业——Alpha项目测试 格式描述: 这个作业属于哪个课程 2019秋软工17级系统分析与设计 这个作业要求在哪里 作业要求 团队名称 杨荣模杰和他的佶祥虎 这个作业的目标 测试其他组项目并写 ...

随机推荐

  1. Android应用开发:网络工具——Volley(一)

    引言 网络一直是我个人的盲点,前一阵子抽空学习了一下Volley网络工具的用法,也透过源代码进行了进一步的学习,有一些心得想分享出来.在Android开发中,成熟的网络工具不少,Android自带了H ...

  2. rtems 4.11 IRQ (arm,beagle)

    arm IRQ入口在 cpukit/score/arm/arm_exec_interrupt.S 中,其中BSP最关心就是 bl bsp_interrupt_dispatch 这句,看看beagle ...

  3. python升级安装后的yum的修复

    升级python版本号后,执行yum # yum -y install openssl 提演示样例如以下: There was a problem importing one of the Pytho ...

  4. android studio 更新Gradle版本号方法

    在导入其它项目时,常常因为gradle版本号不一致而导致不能编译 解决方法: 第一步: 按提示点击让它下载.事实上目的并非要它下载.因为这样速度会非常慢.这样做仅仅是为了让它在本地创建相应的文件夹结构 ...

  5. redis配置认证密码(转)

    redis配置密码 1.通过配置文件进行配置yum方式安装的redis配置文件通常在/etc/redis.conf中,打开配置文件找到 ? 1 #requirepass foobared 去掉行前的注 ...

  6. opensearch空查询

    query子句不支持为空的查询,可以使用filter子句:filter=area=""   或者 filter=filedlen(area)=0 可以使用相关性函数实现:https ...

  7. create-react-app创建项目报错SyntaxError: Unexpected end of JSON input while parsing near '...ttachment":false,"tar' npm代理

    SyntaxError: Unexpected end of JSON input while parsing near '...ttachment":false,"tar' 错误 ...

  8. 成长型思维模式Not yet

    当做一件事失败了,要告诉他 暂未成功,暂时没有成功,继续努力,下次就有可能成功. 不及格,暂未及格  是两种思维模式,成长性的思维方式得到的是一个是努力型的人格

  9. TP框架---thinkphp修改删除数据

    1.在控制器MainController里面写一个方法,调用Nation表中的数据. public function zhuyemian() { $n = D("Nation"); ...

  10. EasyPlayer Android RTSP播放器延迟再优化策略

    EasyPlayer延迟再优化策略 EasyPlayer是一款专门针对RTSP协议进行过优化的播放器.其中两个我们引以为傲的的优点就是起播快和低延迟.最近我们遇到一些需求,其对延迟要求非常苛刻,于是我 ...