bzoj3648: 寝室管理(环套树+点分治)
好题。。写了两个半小时hh,省选的时候要一个半小时内调出这种题目还真是难= =
题目大意是给一棵树或环套树,求点距大于等于K的点对数
这里的树状数组做了一点变换。不是向上更新和向下求和,而是反过来,所以求和的时候sum(k)实际上是求k到n的和
所以我们要求大于等于k的dis的次数和,就是求sum(1,k-1),注意k要减一
如果是树,就是常规的点分治,然后用树状数组维护dis【t】出现的次数
如果是环套树,找环之后割掉一条边,然后先求这棵树的答案。接着考虑过了这条割掉的边s--t的情况:我们以这条边的一点t为起点,对于环上的每个点(即每棵子树的根),我们求出这棵子树的所有dis后,dis+cir_len-i为所求链的第一部分,链的第二部分的长度为k-(dis+cir_len-i),用树状数组求就可以了。更新树状数组的时候不是更新dis,而是dis+i;i即根到割的那条边的另一个点s的距离&&这条割边
完美解决。。然而常数还是很大,跑了两秒多
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define INF 0x3f3f3f3f
#define LL long long
using namespace std;
;
struct node{
int to,next;
}e[maxn*];
int n,m,K,head[maxn],size[maxn],vis[maxn],sz,total,root,dis[maxn],tot,fa[maxn];
;
LL p[maxn*],ans;
void insert(int u, int v){
e[++tot].to=v; e[tot].next=head[u]; head[u]=tot;
}
void add(int x, LL c){
for (;x;x-=x&-x) p[x]+=c;
}
LL query(int x){ //注意:这里的树状数组是倒过来的, query(1,k) 是求得k+1到n
LL ret=;
) x=;
*n;x+=x&-x) ret+=p[x];
return ret;
}
void getroot(int u, int f){
size[u]=; ;
for (int v,i=head[u]; i; i=e[i].next){
if (vis[v=e[i].to] || v==f || i==ban1 || i==ban2) continue;
getroot(v,u);
size[u]+=size[v];
mx=max(mx,size[v]);
}
mx=max(mx,total-size[u]);
if (mx<sz) sz=mx,root=u;
}
void getdis(int u, int f, int d){
dis[++tot]=d;
for (int i=head[u],v; i; i=e[i].next){
if (vis[v=e[i].to] || v==f || i==ban1 || i==ban2) continue;
getdis(v,u,d+);
}
}
void work(int u){
total=size[u]?size[u]:n;
sz=INF;
getroot(u,); u=root;
vis[u]=; tot=;
; i; i=e[i].next){
if (vis[v=e[i].to] || i==ban1 || i==ban2) continue;
last=tot;
getdis(v,,); //printf("%d\n", tot);
; j<=tot; j++) ans+=query(K--dis[j]);
; j<=tot; j++) add(dis[j],);
}
ans+=query(K-);
);
for (int v,i=head[u]; i; i=e[i].next)
if (!vis[v=e[i].to] && i!=ban1 && i!=ban2) work(v);
}
void find_cir(int u, int f){
vis[u]=; if (len) return;//printf(" %d\n", u);
for (int i=head[u],v; i; i=e[i].next){
v=e[i].to;
if (v==f || len) continue;
fa[v]=u;// printf("now %d\n", u);
if (vis[v]){
ban1=i; ban2=i^;
for (int x=fa[v]; x!=v; x=fa[x]) cir[++len]=x; cir[++len]=v;
return;
}
find_cir(v,u);
}
}
void cut(){
; i<=n; i++) vis[i]=;
work();// printf(" %lld\n", ans);
; i<=n; i++) p[i]=0LL,vis[i]=;
; i<=len; i++) vis[cir[i]]=;
; i<=len; i++){
;
getdis(u,,); //printf(" %d\n", tot);
; j<=tot; j++) ans+=query(K-dis[j]-(len-i+));//, printf("%lld\n", ans);
);
}
}
int main(){
scanf(;
,u,v; i<=m; i++){
scanf("%d%d", &u, &v);
insert(u,v); insert(v,u);
}
) work();
else{
find_cir(,);
cut();
}
printf("%lld\n", ans);
;
}
bzoj3648: 寝室管理(环套树+点分治)的更多相关文章
- 【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 : 寝室管理
求环套外向树上节点数不小于K的路径数. 首先树的话直接点分治+树状数组$O(n\log^2n)$搞定 环套树的话,先删掉多余的边(a,b) 然后变成了一棵树,直接点分治 然后在树上找到a到b的路径,将 ...
- 【bzoj3648】环套树+点分治+树状数组
tree 1s 128M by hzw czy神犇种了一棵树,他想知道地球的质量 给定一棵n个点的树,求树上经过点的个数≥K的路径数量ans 对于部分数据,树上某两点间会多出最多一条无向边 输入数据 ...
- 【BZOJ3648】寝室管理 树分治
[BZOJ3648]寝室管理 Description T64有一个好朋友,叫T128.T128是寄宿生,并且最近被老师叫过去当宿管了.宿管可不是一件很好做的工作,碰巧T128有一个工作上的问题想请T6 ...
- BZOJ 3648: 寝室管理( 点分治 + 树状数组 )
1棵树的话, 点分治+你喜欢的数据结构(树状数组/线段树/平衡树)就可以秒掉, O(N log^2 N). 假如是环套树, 先去掉环上1条边, 然后O(N log^2 N)处理树(同上); 然后再O( ...
- [ARC083F] Collecting Balls [建二分图+环套树定向+建拓扑图+树的拓扑序计数]
题面 [传送门](https://arc083.contest.atcoder.jp/tasks/arc083_d) 思路 这是一道真正的好题 第一步:转化模型 行列支配类的问题,常见做法就是把行和列 ...
- 【BZOJ-1040】骑士 树形DP + 环套树 + DFS
1040: [ZJOI2008]骑士 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3312 Solved: 1269[Submit][Status ...
- 【BZOJ】1040: [ZJOI2008]骑士(环套树dp)
http://www.lydsy.com/JudgeOnline/problem.php?id=1040 简直不能再神的题orz. 蒟蒻即使蒟蒻,完全不会. 一开始看到数据n<=1000000就 ...
随机推荐
- MD5加密
public string Second_MD5(string str) { MD5 md5 = MD5.Create();//创建MD5实例 byte[] strbyte = Encoding.UT ...
- doT.js学习
doT.js特点是快,小,无依赖其他插件.但是一般和jquery一起使用 官网:http://olado.github.io 使用方法:{{= }} for interpolation{{ }} fo ...
- web 开发入门
一 :进入Web JAVASE:标准 - standard JAVA 桌面程序 GUI SOCKET JAVAEE:企业-浏览器控制 WEB 二:软件结构: c/s :clie ...
- 集合 LinkedList、ArrayList、Set、Treeset
LinkedList中特有的方法: 1:方法介绍 addFirst(E e) addLast(E e) getFirst() getLast() removeFirst() removeLast() ...
- 前端自学vs跟大神系统学?你看着办
前端自学vs跟大神系统学?你看着办 一名广告专业学生,在大三的时候对于广告行业的前景不是很看好,转而自学web前端,刚开始接触的前端语言是html(html应该不算编程语言),上手很容易,在w3csh ...
- 113使用FOR做九九税法表-不知道为什么自己的编译器实现不了制表符
package com.chongrui.test;/* *使用FOR做九九税法表 * * * */public class test { public static void main(S ...
- 《Scalable IO in Java》笔记
Scalable IO in Java http://gee.cs.oswego.edu/dl/cpjslides/nio.pdf 基本上所有的网络处理程序都有以下基本的处理过程:Read reque ...
- AgileEAS.NET SOA中间件平台更新日志 2015-04-28
一.前言 AgileEAS.NET SOA 中间件平台是一款基于基于敏捷并行开发思想和Microsoft .Net构件(组件)开发技术而构建的一个快速开发应用平台.用于帮助中小型软件企业建立一条适合市 ...
- PyQt5+Python3.5.2-32bit开发环境搭建
1.基本环境. Window 8.1 64bit Python3.5.2-32bit.exe PyQt5 2.安装python. 去官网下载32位版本的python3.5.2(就是x86那个) 备 ...
- JQuery的无缝滚动
图片无缝向左滚动的代码如下: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "h ...