【题解】

  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 寝室管理的更多相关文章

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

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

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

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

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

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

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

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

  5. BZOJ3648 : 寝室管理

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

  6. BZOJ3648:寝室管理

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

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

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

  8. BZOJ 4196 软件包管理器

    树链剖分 建树之后,安装软件就是让跟节点到安装的节点路径所有点权+1,卸载软件就是让一个节点和他的子数-1 要求变化数量的话直接求和相减就行啦(绝对值) 注意一点,一开始的lazyatag应该是-1, ...

  9. BZOJ - 4196 软件包管理器 (树链剖分+dfs序+线段树)

    题目链接 设白色结点为未安装的软件,黑色结点为已安装的软件,则: 安装软件i:输出结点i到根的路径上的白色结点的数量,并把结点i到根的路径染成黑色.复杂度$O(nlog^2n)$ 卸载软件i:输出结点 ...

随机推荐

  1. 2017阿里给Java开发者的两个福利

    一.<Java开发规约> 无规矩不成方圆 无规范不能协作. 2017年开春之际,诚意献上重磅大礼:阿里巴巴Java开发手册,首次公开阿里官方Java代码规范标准.这套Java统一规范标准将 ...

  2. 【单独编译使用WebRTC的音频处理模块 - android】

    更新 [2015年2月15日] Bill 这段时间没有再关注 WebRTC 以及音频处理的相关信息,且我个人早已不再推荐单独编译 WebRTC 中的各个模块出来使用.实际上本文的参考价值已经很小了,甚 ...

  3. bzoj 2100: [Usaco2010 Dec]Apple Delivery【spfa】

    洛谷数据好强啊,普通spfa开o2都过不了,要加双端队列优化 因为是双向边,所以dis(u,v)=dis(v,u),所以分别以pa1和pa2为起点spfa一遍,表示pb-->pa1-->p ...

  4. bzoj 1627: [Usaco2007 Dec]穿越泥地【bfs】

    在洛谷上被卡了一个点开了O2才过= = bfs即可,为方便存储,把所有坐标+500 #include<iostream> #include<cstdio> #include&l ...

  5. P3207 [HNOI2010]物品调度

    传送门 完了题目看错了--还以为所有的\(x,y\)都要一样--结果题解都没看懂-- 先考虑如果已经求出了所有的\(pos\)要怎么办,那么我们可以把\(0\)也看做是一个箱子,然后最后每个箱子都在一 ...

  6. golang——database/sql包学习

    1.database/sql包 sql包提供了保证SQL或类SQL数据库的泛用接口. 使用sql包时必须注入(至少)一个数据库驱动. (1)获取mysql driver:go get -v githu ...

  7. 洛谷2019 3月月赛 T2

    题干 洛谷同款 T2?(看似比T1简单些) 二维前缀和嘛?[多简单 我天天拿二维前缀和水DP] 这是前缀和的预处理 2333 处理出来所有的情况 某个地方要加上mod再%mod 如果没有这一步 那么 ...

  8. spring 简单实现BeanFactory(转)

    原文地址: http://blog.csdn.net/mlc1218559742/article/details/52776160 有没有发现上面的代码与利用反射实现工厂模式的代码很相似.对,你没有看 ...

  9. php 5.6 版本配置 oracle ddl

    1. Windows版PHP内置了Oracle驱动,在ext目录下:php_oci8.dllphp_oci8_11g.dllphp_pdo_oci.dllLinux上如果自己编译的话则添加下面的con ...

  10. 239 Sliding Window Maximum 滑动窗口最大值

    给定一个数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧.你只可以看到在滑动窗口 k 内的数字.滑动窗口每次只向右移动一位.例如,给定 nums = [1,3,-1,-3, ...