【BZOJ3648】寝室管理

Description

T64有一个好朋友,叫T128。T128是寄宿生,并且最近被老师叫过去当宿管了。宿管可不是一件很好做的工作,碰巧T128有一个工作上的问题想请T64帮忙解决。T128的寝室条件不是很好,所以没有很多钱来装修。礼间寝室仅由n-1条双向道路连接,而且任意两间寝室之间都可以互达。最近,T128被要求对一条路径上的所有寝室进行管理,这条路径不会重复经过某个点或某条边。但他不记得是哪条路径了。他只记得这条路径上有不少于k个寝室。于是,他想请T64帮忙数一下,有多少条这样的路径满足条件。嗯…还有一个问题。由于最近有一些熊孩子不准晚上讲话很不爽,他们决定修筑一条“情报通道”,如果通道建成,寝室就变成了一个N个点N条边的无向图。并且,经过“情报通道”的路径也是合法的。T128心想:通道建成之前,T64还有一个高效的算法帮我数路径条数,但是通道建成之后,他还有办法吗?对,T64手忙脚乱,根本数不清有多少条路径。于是他找到了你。

Input

第一行为三个正整数N,M,K(2 ≤ K ≤ N),代表有n间寝室,m条边连接它们n-1 ≤ m ≤ N;
m= n-1意味着“情报遁道”未被修好;m=n意味着“情报通道”已被修好),以及题目描述中的K。
接下来m行,每行两个正整数z,y,代表第x间寝室与第y间寝室之间有一条双向边。

Output

仅包含一个整数,代表经过至少K间寝室的路径条数。

Sample Input

5 5 2
1 3
2 4
3 5
4 1
5 2

Sample Output

20

HINT

N≤100000
K≤N
M=N

题解:现将环上的所有边都拆开,对于不经过环上的边的路径,我们可以对每个子树都用树分治解决,具体做法可以采用树形DP式+树状数组或容斥式+双指针,复杂度都是$O(nlog^2_n)$的。

对于经过环的路径,我们乱@%#^&^^搞即可。

好吧具体细节还是见代码吧。

#include <cstdio>
#include <cstring>
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const int maxn=100010;
int f[maxn<<1],to[maxn<<1],next[maxn<<1],head[maxn],vis[maxn],s[maxn<<1],siz[maxn],tim[maxn<<1],d[maxn],p[maxn];
vector<int> ch[maxn];
int n,m,K,mn,tot,cnt,rt,now,len;
ll ans;
queue<int> q;
inline void add(int a,int b)
{
to[cnt]=b,next[cnt]=head[a],head[a]=cnt++;
}
inline void updata(int x,int v)
{
for(int i=x;i;i-=i&-i)
{
if(tim[i]<now) tim[i]=now,s[i]=0;
s[i]+=v;
}
}
inline int query(int x)
{
if(x<=0) x=1;
int ret=0,i;
for(i=x;i<=2*n;i+=i&-i)
{
if(tim[i]<now) tim[i]=now,s[i]=0;
ret+=s[i];
}
return ret;
}
void getrt(int x,int fa)
{
siz[x]=1;
int tmp=0,i;
for(i=head[x];i!=-1;i=next[i]) if(to[i]!=fa&&!vis[to[i]])
getrt(to[i],x),tmp=max(tmp,siz[to[i]]),siz[x]+=siz[to[i]];
tmp=max(tmp,tot-siz[x]);
if(tmp<mn) mn=tmp,rt=x;
}
int getdep(int x,int fa,int dep)
{
f[dep]++;
int i,tmp=dep;
for(i=head[x];i!=-1;i=next[i]) if(to[i]!=fa&&!vis[to[i]]) tmp=max(tmp,getdep(to[i],x,dep+1));
return tmp;
}
void solve(int x)
{
vis[x]=1,now++;
int i,j,tmp;
for(i=head[x];i!=-1;i=next[i]) if(!vis[to[i]])
{
tmp=getdep(to[i],x,1);
for(j=1;j<=tmp;j++) ans+=(ll)(query(K-j-1)+(j>=K-1))*f[j];
for(j=1;j<=tmp;j++) updata(j,f[j]),f[j]=0;
}
for(i=head[x];i!=-1;i=next[i]) if(!vis[to[i]])
mn=1<<30,tot=siz[to[i]],getrt(to[i],x),solve(rt);
}
void dfs(int x)
{
p[++len]=x,d[x]=-2;
for(int i=0;i<(int)ch[x].size();i++) if(d[ch[x][i]]==-1) dfs(ch[x][i]);
}
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-') f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+(gc^'0'),gc=getchar();
return ret*f;
}
int main()
{
//freopen("bz3648.in","r",stdin);
n=rd(),m=rd(),K=rd();
int i,j,u,a,b,tmp;
memset(head,-1,sizeof(head));
if(n>m)
{
for(i=1;i<n;i++) a=rd(),b=rd(),add(a,b),add(b,a);
tot=n,mn=1<<30,getrt(1,0),solve(rt);
printf("%lld",ans);
return 0;
}
for(i=1;i<=n;i++) a=rd(),b=rd(),ch[a].push_back(b),ch[b].push_back(a),d[a]++,d[b]++;
for(i=1;i<=n;i++) if(d[i]==1) q.push(i);
while(!q.empty())
{
u=q.front(),q.pop();
for(i=0;i<(int)ch[u].size();i++)
{
d[ch[u][i]]--;
if(!d[ch[u][i]]) add(u,ch[u][i]),add(ch[u][i],u);
if(d[ch[u][i]]==1) q.push(ch[u][i]);
}
}
for(i=1;i<=n;i++) if(d[i]>1) u=i,d[i]=-1;
dfs(u);
for(i=1;i<=len;i++) for(j=0;j<(int)ch[p[i]].size();j++) if(d[ch[p[i]][j]]!=-2)
add(ch[p[i]][j],p[i]),add(p[i],ch[p[i]][j]);
for(i=1;i<=len;i++) tot=n,mn=1<<30,getrt(p[i],0),solve(rt);
now++;
memset(vis,0,sizeof(vis));
for(i=1;i<=len;i++)
{
tmp=getdep(p[i],0,1);
for(j=1;j<=tmp;j++) ans+=(ll)query(K-(i+j)+1+n)*f[j];
for(j=1;j<=tmp;j++) updata(j-i+n,f[j]),f[j]=0;
}
now++;
for(i=1;i<=len;i++)
{
tmp=getdep(p[i],0,1);
for(j=1;j<=tmp;j++) ans+=(ll)query(K+1-len+i-j)*f[j];
for(j=1;j<=tmp;j++) updata(i+j,f[j]),f[j]=0;
}
printf("%lld",ans);
return 0;
}

【BZOJ3648】寝室管理 树分治的更多相关文章

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

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

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

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

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

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

  4. BZOJ3648 : 寝室管理

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

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

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

  6. BZOJ3648:寝室管理

    浅谈树分治:https://www.cnblogs.com/AKMer/p/10014803.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem. ...

  7. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

  8. hdu-5977 Garden of Eden(树分治)

    题目链接: Garden of Eden Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/ ...

  9. 【BZOJ-1468】Tree 树分治

    1468: Tree Time Limit: 10 Sec  Memory Limit: 64 MBSubmit: 1025  Solved: 534[Submit][Status][Discuss] ...

随机推荐

  1. Objective-C的内存管理(一)黄金法则的理解

    转自:http://blog.csdn.net/lonelyroamer/article/details/7666851 一.内存管理黄金法则: The basic rule to apple is ...

  2. Linux 进程资源用量监控和按用户设置进程限制

    每个 Linux 系统管理员都应该知道如何验证硬件.资源和主要进程的完整性和可用性.另外,基于每个用户设置资源限制也是其中一项必备技能. 在这篇文章中,我们会介绍一些能够确保系统硬件和软件正常工作的方 ...

  3. Out of Hay(poj2395)(并查集)

    Out of Hay Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11580   Accepted: 4515 Descr ...

  4. 服务器端cs文件

    服务器端向mysql数据库写数据 using System; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System.Colle ...

  5. java服务端json结果集传值给前端的数据输出格式

    在服务端输出json数据时按照一定的格式输出时间字段,fastjson支持两种方式:1.使用JSON.toJSONStringWithDateFormat方法2.JSON.toJSONString方法 ...

  6. ubuntu 12.04下apache 配置家目录地址

    apache2 最在搞前端相关的东西,上一次也记录了 Linux 下 LAMP环境的搭建,现在记录一下如果改变 apache2 的家目录地址该怎么做,改那个配置文件 修改配置文件 /etc/apach ...

  7. debug宏起作用应用

    在linux内核中重新定义了printk,如pr_debug,dev_dbg等.要使用这些宏函数就需要定义DEBUG. 详见:kernel printk信息显示级别 那么DEBUG该定义在什么地方呢? ...

  8. linux系统中/etc/syslog.conf文件解读

    1: syslog.conf的介绍 对于不同类型的Unix,标准UnixLog系统的设置,实际上除了一些关键词的不同,系统的syslog.conf格式是相同的.syslog采用可配置的.统一的系统登记 ...

  9. [转]hadoop,spark,storm,pig,hive,mahout等到底有什么区别和联系?

    摘自知乎大神的论述 作者:Xiaoyu Ma链接:https://www.zhihu.com/question/27974418/answer/38965760来源:知乎著作权归作者所有,转载请联系作 ...

  10. ssh2——Interceptor拦截器

    尽管没学过struts1吧.可是了解到struts1中并没有拦截器,  到Struts2才有.它是基于WebWork发展起来的, 顾名思义,说到拦截器大家首先肯定会想到它是拦截东西的,起到一个限制的作 ...