BZOJ 3648 寝室管理

【题解】
GDOI2016 Day2T3
如果给出的数据是一棵树那么皆大欢喜直接点分治就好了,用树状数组维护大于x的数的个数。如果是一棵基环树,我们先断掉环上的一条边,然后跑点分治;再加上经过这条边的方案数,其实就是从断掉的那条边的一个端点开始,把环遍历一遍,更新贡献的方式跟点分治过程中的差不多,具体看注释2333。
#include<cstdio>
#include<algorithm>
#define rg register
#define N 100010
#define LL long long
using namespace std;
int n,m,k,tot,cnt,top,cir,root;
int last[N],dep[N],bit[N<<],siz[N],mxsiz[N],st[N],c[N];
bool cut[N<<],v[N];
LL ans=;
struct edge{
int to,pre,dis;
}e[N<<];
inline int read(){
int k=,f=; char c=getchar();
while(c<''||c>'')c=='-'&&(f=-),c=getchar();
while(''<=c&&c<='')k=k*+c-'',c=getchar();
return k*f;
}
inline void add(int x,int y){for(;x>;x-=(x&-x))bit[x]+=y;}
inline int query(int x){
if(x<) x=; int ret=;
for(;x<=n+cir;x+=(x&-x)) ret+=bit[x]; return ret;
}
void findcircle(int x,int fa){
if(cir) return;
if(v[x]){
c[cir=]=x;
for(rg int i=top;st[i]!=x;c[++cir]=st[i--]);
}
v[x]=; st[++top]=x;
for(rg int i=last[x],to;i;i=e[i].pre)
if((to=e[i].to)!=fa) findcircle(to,x);
v[x]=; top--;
}
void getroot(int x,int fa){
siz[x]=; mxsiz[x]=;
for(rg int i=last[x],to;i;i=e[i].pre)if(!v[to=e[i].to]&&to!=fa&&!cut[i]){
getroot(to,x); siz[x]+=siz[to];
mxsiz[x]=max(mxsiz[x],siz[to]);
}
mxsiz[x]=max(mxsiz[x],cnt-mxsiz[x]);
if(!root||mxsiz[x]<mxsiz[root]) root=x;
}
void getdep(int x,int fa,int d){
st[++top]=d;
for(rg int i=last[x],to;i;i=e[i].pre)
if(!v[to=e[i].to]&&to!=fa&&!cut[i]) getdep(to,x,d+);
}
void dfs(int x){
int l=; v[x]=;
for(rg int i=last[x],to;i;i=e[i].pre)
if(!v[to=e[i].to]&&!cut[i]){
l=top+; getdep(to,x,);
for(rg int j=l;j<=top;j++) ans+=query(k-st[j]-);
for(rg int j=l;j<=top;j++) add(st[j],);
}
ans+=query(k-);
while(top) add(st[top--],-);
for(rg int i=last[x],to;i;i=e[i].pre)
if(!v[to=e[i].to]&&!cut[i]&&siz[to]>=k){
cnt=siz[to]; root=; getroot(to,x); dfs(root);
}
}
int main(){
n=read(); m=read(); k=read();
for(rg int i=;i<=m;i++){
int u=read(),v=read();
e[++tot]=(edge){v,last[u]}; last[u]=tot;
e[++tot]=(edge){u,last[v]}; last[v]=tot;
}
if(m<n){
cnt=n; root=; getroot(,); dfs(root);
}
else{
findcircle(,);
for(rg int i=last[c[]],to;i;i=e[i].pre)if((to=e[i].to)==c[cir]){
cut[i]=; break;
}
for(rg int i=last[c[cir]],to;i;i=e[i].pre)if((to=e[i].to)==c[]){
cut[i]=; break;
}
top=; cnt=n; root=;
getroot(,); dfs(root);
top=;
for(rg int i=;i<=n;i++)v[i]=;
for(rg int i=;i<=cir+n;i++) bit[i]=;
for(rg int i=;i<=cir;i++) v[c[i]]=;
for(rg int i=;i<=cir;i++){
v[c[i]]=;
getdep(c[i],,);
v[c[i]]=;
for(rg int j=;j<=top;j++)ans+=query(k-(cir-i+)-st[j]);//cir-i+1是绕一圈到环上起点的距离
while(top) add(st[top--]+i,);//+i就是加上到环上起点的距离
}
}
printf("%lld\n",ans);
return ;
}
BZOJ 3648 寝室管理的更多相关文章
- BZOJ 3648: 寝室管理( 点分治 + 树状数组 )
1棵树的话, 点分治+你喜欢的数据结构(树状数组/线段树/平衡树)就可以秒掉, O(N log^2 N). 假如是环套树, 先去掉环上1条边, 然后O(N log^2 N)处理树(同上); 然后再O( ...
- 【BZOJ-3648】寝室管理 环套树 + 树状数组 + 点分治
3648: 寝室管理 Time Limit: 40 Sec Memory Limit: 512 MBSubmit: 239 Solved: 106[Submit][Status][Discuss] ...
- BZOJ3648 寝室管理 【点分治 + 环套树】
3648: 寝室管理 Time Limit: 40 Sec Memory Limit: 512 MB Submit: 366 Solved: 152 [Submit][Status][Discus ...
- 【BZOJ3648】寝室管理 树分治
[BZOJ3648]寝室管理 Description T64有一个好朋友,叫T128.T128是寄宿生,并且最近被老师叫过去当宿管了.宿管可不是一件很好做的工作,碰巧T128有一个工作上的问题想请T6 ...
- BZOJ3648 : 寝室管理
求环套外向树上节点数不小于K的路径数. 首先树的话直接点分治+树状数组$O(n\log^2n)$搞定 环套树的话,先删掉多余的边(a,b) 然后变成了一棵树,直接点分治 然后在树上找到a到b的路径,将 ...
- BZOJ3648:寝室管理
浅谈树分治:https://www.cnblogs.com/AKMer/p/10014803.html 题目传送门:https://www.lydsy.com/JudgeOnline/problem. ...
- bzoj3648: 寝室管理(环套树+点分治)
好题..写了两个半小时hh,省选的时候要一个半小时内调出这种题目还真是难= = 题目大意是给一棵树或环套树,求点距大于等于K的点对数 这里的树状数组做了一点变换.不是向上更新和向下求和,而是反过来,所 ...
- BZOJ 4196 软件包管理器
树链剖分 建树之后,安装软件就是让跟节点到安装的节点路径所有点权+1,卸载软件就是让一个节点和他的子数-1 要求变化数量的话直接求和相减就行啦(绝对值) 注意一点,一开始的lazyatag应该是-1, ...
- BZOJ - 4196 软件包管理器 (树链剖分+dfs序+线段树)
题目链接 设白色结点为未安装的软件,黑色结点为已安装的软件,则: 安装软件i:输出结点i到根的路径上的白色结点的数量,并把结点i到根的路径染成黑色.复杂度$O(nlog^2n)$ 卸载软件i:输出结点 ...
随机推荐
- IntelliJ IDEA 缓存和索引介绍
转自:https://www.cnblogs.com/zhanghaibinblogs/p/6722061.html IDEA 在首次加载项目的时候都会创建索引,IDEA 的缓存和索引主要是用来加快文 ...
- P3573 [POI2014]RAJ-Rally
传送门 很妙的思路 首先这是一个DAG,于是我们先在原图和反图上各做一遍,分别求出\(diss_i\)和\(dist_i\)表示从\(i\)点出发的最短路和以\(i\)为终点的最短路 我们考虑把点分为 ...
- [ TJOI 2007 ] 线段
\(\\\) \(Description\) 一个\(N\times N\) 的网格,每行有一段要必走,求从\((1,1)\)到\((N,N)\)的最短路长度. \(N\le 2\times10^4\ ...
- CF 334 div.2-D Moodular Arithmetic
思路: 易知k = 0的时候答案是pp-1,k = 1的时候答案是pp. 当k >= 2的时候,f(0) = 0,对于 1 <= n <= p - 1,如果f(n)确定,由题意可知f ...
- 关于百度地图导航AndroidSDK的初始化问题
使用百度地图有一段时间了,导航是一个一直困扰我的问题.今天刚发现百度地图的导航SDK并不是对Android6.0版本不兼容.而是对某一部分手机不兼容,准确的说是对X64或X86的cpu不兼容.下载百度 ...
- SQLState: 23000
今天登陆项目的时候,报500,日志显示如下: 解决办法是: 首先,删除序列:DROP SEQUENCE sys_log_seq 然后,新建序列:CREATE SEQUENCE sys_log_seq ...
- dbcp数据源配置
<bean id="dbcpDataSource" class="org.apache.commons.dbcp.BasicDataSource" de ...
- Zynq7000系列之芯片引脚功能综述
很多人做了很久的FPGA,知道怎么去给信号分配引脚,却对这些引脚的功能及其资源限制知之甚少:在第一章里对Zynq7000系列的系统框架进行了分析和论述,对Zynq7000系列的基本资源和概念有了大致的 ...
- [转]最值得拥有的免费Bootstrap后台管理模板
在PHP开发项目中,后台管理因为面向群体相对比较固定,大部分以实现业务逻辑和功能.使用Bootstrap后台模板可以让后端开发很轻松的就展现给客户一个响应式的后台,节约前端开发的时间.下面PHP程序员 ...
- golang tar gzip 压缩,解压(含目录文件)
tar是用于文件归档,gzip用于压缩.仅仅用tar的话,达不到压缩的目的.我们常见的tar.gz就是用gzip压缩生成的tar归档文件. go实现tar压缩与解压与zip类似,区别在于tar需要使用 ...