题面在这里!

正式告别文化课回归的第一题QWQ,然鹅半个月之后还是要退役QWQWQWQWQ

好像很久之前就见过的一个题,当时只会打一打 O(N^2) 的暴力QWQ,正好今天又写了遍这个暴力用来对拍23333

正解的话就是把O(N^2)的暴力用数据结构优化一下。

(按照常规套路,先把树建成有根树,以1为根)

考虑把原问题建模,每条边的贡献就是这条边 i 的特征0/1数组的区间内不止一种数的区间数,特征数组a[]是指,如果点x在边i下面,那么a[x]=1;否则a[x]=0。

这个显然补集转化一下会更加简单,于是问题变成了如何快速的求每条边的特征数组的区间内只有一种数的区间数。。。。

明显具有可合并性嘛QWQ,直接把子树的一坨数组合并一下(因为1不可能重),然后把当前扫的根x的a[x]=1就行了。

直接合并还是O(N^2)的,不过改成线段树合并就只有N带log啦QWQ。。。。。

写之前搞清楚需要什么信息以及怎么合并就行啦(对于窝这种不爱写数据结构的老年养生选手来说还是写起来比较麻烦的QWQ)。

#include<bits/stdc++.h>
#define ll long long
using namespace std;
#define mid (l+r>>1)
#define LC lc[o]
#define RC rc[o]
const int N=100005,lg=37; int lc[N*lg],rc[N*lg],lt[N*lg],rt[N*lg],uu,vv;
int cnt,n,m,rot[N],llen[N*lg],rlen[N*lg];
int to[N*2],ne[N*2],hd[N],num=0,le,ri;
ll sum[N*lg],ans; inline void add(int x,int y){ to[++num]=y,ne[num]=hd[x],hd[x]=num;} inline void build(int L){
cnt++,lt[cnt]=rt[cnt]=0;
llen[cnt]=rlen[cnt]=L;
sum[cnt]=L*(ll)(L+1)>>1;
} inline void maintain(int o,int l,int r){
lt[o]=lt[LC],rt[o]=rt[RC];
llen[o]=llen[LC]+((llen[LC]==mid-l+1&&lt[LC]==lt[RC])?llen[RC]:0);
rlen[o]=rlen[RC]+((rlen[RC]==r-mid&&rt[RC]==rt[LC])?rlen[LC]:0);
sum[o]=sum[LC]+sum[RC]+(rt[LC]==lt[RC]?rlen[LC]*(ll)llen[RC]:0);
} void update(int o,int l,int r){
if(l==r){ sum[o]=llen[o]=rlen[o]=lt[o]=rt[o]=1; return;} if(!lc[o]) build(mid-l+1),lc[o]=cnt;
if(!rc[o]) build(r-mid),rc[o]=cnt; if(le<=mid) update(LC,l,mid);
else update(RC,mid+1,r); maintain(o,l,r);
} int Merge(int x,int y,int l,int r){
if(!x||!y) return x+y;
if(l==r||(!rc[x]&&!rc[y]&&!lc[x]&&!lc[y])) return lt[x]?x:y; if(lc[x]||lc[y]) lc[x]=Merge(lc[x],lc[y],l,mid);
if(rc[x]||rc[y]) rc[x]=Merge(rc[x],rc[y],mid+1,r); maintain(x,l,r);
return x;
} /*
void B(int o,int l,int r){
printf("%d %d %d %d %d %d %d %lld\n",o,l,r,lt[o],rt[o],llen[o],rlen[o],sum[o]); if(l==r) return; if(lc[o]) printf("%d is son of %d\n",lc[o],o),B(lc[o],l,mid);
if(rc[o]) printf("%d is son of %d\n",rc[o],o),B(rc[o],mid,r);
}
*/ void dfs(int x,int fa){
build(n),rot[x]=cnt; le=x,update(rot[x],1,n); for(int i=hd[x];i;i=ne[i])
if(to[i]!=fa) dfs(to[i],x),rot[x]=Merge(rot[x],rot[to[i]],1,n); if(fa) ans-=sum[rot[x]]; // if(x==4) B(rot[x],1,n);
} int main(){
// freopen("data.in","r",stdin);
// freopen("data.out","w",stdout); scanf("%d",&n),ans=(n-1)*(ll)(n+1)*(ll)n>>1;
for(int i=1;i<n;i++)
scanf("%d%d",&uu,&vv),add(uu,vv),add(vv,uu); dfs(1,0);
printf("%lld\n",ans); return 0;
}

  

HihoCoder - 1715 树的连通问题的更多相关文章

  1. hihocoder 1391 树状数组

    #1391 : Countries 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 There are two antagonistic countries, countr ...

  2. DFS序+线段树 hihoCoder 1381 Little Y's Tree(树的连通块的直径和)

    题目链接 #1381 : Little Y's Tree 时间限制:24000ms 单点时限:4000ms 内存限制:512MB 描述 小Y有一棵n个节点的树,每条边都有正的边权. 小J有q个询问,每 ...

  3. hihoCoder 1014trie树(字典树)

    hihoCoder 1014 题目提示已经很清楚了~ 贴代码…… #include <iostream> #include <cstdio> #include <cstr ...

  4. HihoCoder——Trie树

    本文出自:http://blog.csdn.net/svitter 原题:http://hihocoder.com/contest/hiho2/problem/1 题解:使用Trie树..基础题目.一 ...

  5. hihoCoder#1322(树的判定)

    时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 给定一个包含 N 个顶点 M 条边的无向图 G ,判断 G 是不是一棵树. 输入 第一个是一个整数 T ,代表测试数据的组 ...

  6. HihoCoder 1511: 树的方差(prufer序)

    题意 对于一棵 \(n\) 个点的带标号无根树,设 \(d[i]\) 为点 \(i\) 的度数,定义一棵树的方差为数组 \(d[1..n]\) 的方差. 给定 \(n\) ,求所有带标号的 \(n\) ...

  7. #1014 : Trie树 HihoCoder(字典树)

    描述 小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进. 这一天,他们遇到了一本词典,于是小Hi就向小Ho提出了那个经典的问题: ...

  8. hihocoder 1193 树堆 解题报告

    题目大意:给出一棵有根树(根为 \(0\) ),点有点权.可以删除点(非根),并将其子树接到其父亲上.我们称一个树为树堆当前仅当树上每个点都满足其权值大于等于其子树中所有点的点权.现在对于每个点要求其 ...

  9. 2015 北京网络赛 E Border Length hihoCoder 1231 树状数组 (2015-11-05 09:30)

    #1231 : Border Length 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 Garlic-Counting Chicken is a special spe ...

随机推荐

  1. 【NOIP】提高组2012 同余方程

    [算法]扩展欧几里德算法 [题解]学完扩欧就可以随便水了... 转化为不定方程ax-by=1. 因为1且题目保证有解,所以方程有唯一解. 紫书曰:同余方程的一个解其实指的是一个同余等价类. 所以满足x ...

  2. 【洛谷 P4568】 [JLOI2011]飞行路线 (分层最短路)

    题目链接 分层图最短路. 把每个点拆成\(k+1\)个点,表示总共有\(k+1\)层. 然后每层正常连边, 若\((u,v)\)有边,则把每一层的\(u\)和下一层的\(v\).每一层的\(v\)和下 ...

  3. Java案例之士兵作战功能实现

    实现的功能比较简单,主要用到了多态的,抽象类以及模板方法模式这几个知识点.效果图如下,哈哈 ,大神勿喷,后面我会把这些知识点详细介绍出来,即使Java学的不好,只要有一点其他语言基础或者没有应该都能看 ...

  4. linux下守护进程的创建

    最近在学习linux c编程 看到了守护进程的创建,感觉很好玩, 测试环境ubuntu 15.04 下面贴出测试代码 #include <stdio.h> #include <std ...

  5. Android日历开发之右上角标注红点事件

    1.效果如下所示: 2.方法:      前提:已经知道如何在右上角画圆点的情况下.      这是一个任务显示器,每个任务都有一个时间,比如2014.01.12.      如果要标注2016.08 ...

  6. nginx路由文件配置

    nginx中文文档 Nginx 的请求处理有多个阶段,比如说rewrite.access.content等等,不同的配置字段属于不同的配置阶段,不同阶段的先后执行顺序不一样,例如rewrite在con ...

  7. selenium.webdriver.common.keys 模块中常用的变量

    表11-5 selenium.webdriver.common.keys 模块中常用的变量属性 含义Keys.DOWN, Keys.UP, Keys.LEFT,Keys.RIGHT 键盘箭头键Keys ...

  8. C语言的小括号----其实是逗号运算符

    比如下面的代码: #include <stdio.h> void fun() { int a, b, c, d; a = (, b = ); c = (, ); d = (, ); pri ...

  9. python安装基础

    . python安装 //先查看是否存在python的包,如果没有,那可以用yum或去python的官网安装 [root@localhost ~]# rpm -qa|grep python pytho ...

  10. java虚拟机字节码执行引擎

    定义 java虚拟机字节码执行引擎是jvm最核心的组成部分之一,它做的事情很简单:输入的是字节码文件,处理过程是字节码解析的等效过程,输出的是执行结果.在不同的虚拟机实现里,执行引擎在执行java代码 ...