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:输出结点 ...
随机推荐
- HTTP方式播放FLV/mp4 :nginx+Yamdi/MP4BOX
[导语]chrome浏览器确实很强,直接支持MP4拖动播放,对于其他播放器,可以使用以下方法来支持拖动播放.拖动的关键在于生成关键帧等元数据信息,便于服务器和播放器支持拖动. 另外,nginx web ...
- bzoj3786
splay维护dfs序 我们发现有移动子树这种操作,树剖是做不了了,又要实现子树加,lct又维护不了了,这时我们用splay维护入栈出栈序来支持这些操作.我们记录每个点的入栈时间和出栈时间,这样一个闭 ...
- Spark 多项式逻辑回归__二分类
package Spark_MLlib import org.apache.spark.ml.Pipeline import org.apache.spark.ml.classification.{L ...
- Python Flask Web 框架入门
Python Flask 目录 本文主要借鉴 letiantian 的文章 http://www.letiantian.me/learn-flask/ 一.简介 二.安装 三.初始化Flask 四.获 ...
- GCD中各种队列和任务执行方式的组合
一.概念回顾 1.GCD全称 Grand Central Dispatch ,是纯C语言,提供了非常多强大的函数,来进行系统线程的管理. 2.优势:GCD是苹果公司为多核的并行运算提出的解决方案.GC ...
- robotframework - User key 操作
一.用户关键字操作思路 a.创建model1资源 b.在model下创建用户关键字 - 循环 c.测试套件下创建test_case/case2 & 用户关键字 d.测试套件中导入Resourc ...
- 获取openid [微信小程序]
public function wxapi(){ $data=$this->requestdata(); if(!$data['code']) exit(json_encode(array('s ...
- Kafka详解与总结(六)
索引 稀疏存储,每隔一定字节的数据建立一条索引(这样的目的是为了减少索引文件的大小). 下图为一个partition的索引示意图: 注: 现在对6.和8建立了索引,如果要查找7,则会先查找到8然后,再 ...
- VF 查表
题目的意思就是 给你一个数字 n (1~81) 然后问你从 1~10^9 之中有多少个 各位数字之和等于 n 的 数字 我上去 打表了 而且速度还差不多 , 能在 几十分钟内算出来所有答案 ...
- Java多线程(六)守护进程
守护进程:当进程中不存在非守护线程了,则守护线程自动销毁: public class DaemonThread extends Thread{ private int i =0; public voi ...