[洛谷U40581]树上统计treecnt

题目大意:

给定一棵\(n(n\le10^5)\)个点的树。

定义\(Tree[l,r]\)表示为了使得\(l\sim r\)号点两两连通,最少需要选择的边的数量。

求\(\sum_{l=1}^n\sum_{r=l}^nTree[l,r]\)。

思路:

对于每个边考虑贡献,若我们将出现在子树内的点记作\(1\),出现在子树外的点记作\(0\),那么答案就是\(\frac{n(n-1)}2-\)全\(0\)、全\(1\)串的个数。线段树合并,维护前缀/后缀最长全\(0\)/全\(1\)串即可。

时间复杂度\(\mathcal O(n\log n)\)。

源代码:

#include<cstdio>
#include<cctype>
#include<vector>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
typedef long long int64;
const int N=1e5+1,logN=18;
int n;
int64 ans;
std::vector<int> e[N];
inline void add_edge(const int &u,const int &v) {
e[u].push_back(v);
e[v].push_back(u);
}
inline int64 calc(const int &n) {
return 1ll*n*(n-1)/2;
}
struct Node {
int pre[2],suf[2],len;
int64 sum;
Node() {}
Node(const int &l,const bool &v) {
pre[!v]=suf[!v]=0;
pre[v]=suf[v]=len=l;
sum=calc(l);
}
friend Node operator + (const Node &l,const Node &r) {
Node ret;
ret.pre[0]=l.pre[0]+r.pre[0]*(l.pre[0]==l.len);
ret.pre[1]=l.pre[1]+r.pre[1]*(l.pre[1]==l.len);
ret.suf[0]=r.suf[0]+l.suf[0]*(r.suf[0]==r.len);
ret.suf[1]=r.suf[1]+l.suf[1]*(r.suf[1]==r.len);
ret.len=l.len+r.len;
ret.sum=l.sum+r.sum+1ll*l.suf[0]*r.pre[0]+1ll*l.suf[1]*r.pre[1];
return ret;
}
};
class SegmentTree {
#define mid ((b+e)>>1)
private:
Node node[N*logN];
int left[N*logN],right[N*logN];
int sz,new_node() {
return ++sz;
}
int len(const int &b,const int &e) {
return e-b+1;
}
void push_up(const int &p,const int &b,const int &e) {
if(!left[p]) node[p]=Node(len(b,mid),0)+node[right[p]];
if(!right[p]) node[p]=node[left[p]]+Node(len(mid+1,e),0);
if(left[p]&&right[p]) {
node[p]=node[left[p]]+node[right[p]];
}
}
public:
int root[N];
void insert(int &p,const int &b,const int &e,const int &x) {
if(!p) p=new_node();
if(b==e) {
node[p]=Node(1,1);
return;
}
if(x<=mid) insert(left[p],b,mid,x);
if(x>mid) insert(right[p],mid+1,e,x);
push_up(p,b,e);
}
void merge(int &p,const int &q,const int &b,const int &e) {
if(!p||!q) {
p=p|q;
return;
}
if(b==e) return;
merge(left[p],left[q],b,mid);
merge(right[p],right[q],mid+1,e);
push_up(p,b,e);
}
int64 query(const int &p) const {
return node[p].sum;
}
#undef mid
};
SegmentTree t;
void dfs(const int &x,const int &par) {
t.insert(t.root[x],1,n,x);
for(auto &y:e[x]) {
if(y==par) continue;
dfs(y,x);
t.merge(t.root[x],t.root[y],1,n);
}
if(x!=1) ans-=t.query(t.root[x]);
}
int main() {
n=getint();
ans=calc(n)*(n-1);
for(register int i=1;i<n;i++) {
add_edge(getint(),getint());
}
dfs(1,0);
printf("%lld\n",ans);
return 0;
}

[洛谷U40581]树上统计treecnt的更多相关文章

  1. 洛谷 P2664 树上游戏 解题报告

    P2664 树上游戏 题目描述 \(\text{lrb}\)有一棵树,树的每个节点有个颜色.给一个长度为\(n\)的颜色序列,定义\(s(i,j)\) 为 \(i\) 到 \(j\) 的颜色数量.以及 ...

  2. 洛谷 P3177 树上染色 解题报告

    P3177 [HAOI2015]树上染色 题目描述 有一棵点数为\(N\)的树,树边有边权.给你一个在\(0\) ~ \(N\)之内的正整数\(K\),你要在这棵树中选择\(K\)个点,将其染成黑色, ...

  3. 洛谷P2664 树上游戏(点分治)

    题意 题目链接 Sol 神仙题..Orz yyb 考虑点分治,那么每次我们只需要统计以当前点为\(LCA\)的点对之间的贡献以及\(LCA\)到所有点的贡献. 一个很神仙的思路是,对于任意两个点对的路 ...

  4. 洛谷P4242 树上的毒瘤

    解:首先有个套路是一条边的权值是[两端点颜色不同].这个用树剖直接维护,支持修改. 每次询问建虚树,查询虚树上每条边的权值.然后树形DP,用开店的方法,每个点链加链查. #include <bi ...

  5. 树上统计treecnt(dsu on tree 并查集 正难则反)

    题目链接 dalao们怎么都写的线段树合并啊.. dsu跑的好慢. \(Description\) 给定一棵\(n(n\leq 10^5)\)个点的树. 定义\(Tree[L,R]\)表示为了使得\( ...

  6. 洛谷P2664 树上游戏(点分治)

    传送门 题解 因为一个sb错误调了一个晚上……鬼晓得我为什么$solve(rt)$会写成$solve(v)$啊!!!一个$O(logn)$被我硬生生写成$O(n)$了竟然还能过$5$个点……话说还一直 ...

  7. 【刷题】洛谷 P2664 树上游戏

    题目描述 lrb有一棵树,树的每个节点有个颜色.给一个长度为n的颜色序列,定义s(i,j) 为i 到j 的颜色数量.以及 \[sum_i=\sum_{j=1}^ns(i,j)\] 现在他想让你求出所有 ...

  8. 洛谷——P1608 路径统计

    P1608 路径统计 题目描述 “RP餐厅”的员工素质就是不一般,在齐刷刷的算出同一个电话号码之后,就准备让HZH,TZY去送快餐了,他们将自己居住的城市画了一张地图,已知在他们的地图上,有N个地方, ...

  9. 洛谷 P1608 路径统计

    P1608 路径统计 题目描述 “RP餐厅”的员工素质就是不一般,在齐刷刷的算出同一个电话号码之后,就准备让HZH,TZY去送快餐了,他们将自己居住的城市画了一张地图,已知在他们的地图上,有N个地方, ...

随机推荐

  1. dubbo系列四、dubbo服务暴露过程源码解析

    一.代码准备 1.示例代码 参考dubbo系列二.dubbo+zookeeper+dubboadmin分布式服务框架搭建(windows平台) 2.简单了解下spring自定义标签 https://w ...

  2. Websphere MQ Cluster

    大纲: 1.什么是集群 2.建立一个基本的集群 3.DISPLAY命令 4.负载均衡 5.高级配置和管理 6.答疑 7.关于文章.红宝书等 一. 什么是集群       集群就是Websphere M ...

  3. Hyper-V虚拟机上安装一个图形界面的Linux系统

    这件事情呢,一直想干但又觉得太陌生和麻烦,无奈现在到了非装不可的时候,只好硬着头皮去装.在此之前,我不懂什么叫做虚拟机,linux也接触甚少.经过3天的折腾,终于装好了带有图形界面的linux(字符版 ...

  4. Java的初始化执行顺序(父类static变量->子类static变量->父类成员变量->父类构造器->成员变量->构造器->main函数)

    1. 引言 了解Java初始化的顺序,有助于理解Java的初始化机制和内存机制. 顺序:父类static变量->子类static变量->父类成员变量->父类构造器->成员变量- ...

  5. Nginx 下Thinkphp5伪静态

    server { listen 80; server_name all.bjed.com; root "F:\www\asdata"; location / { index ind ...

  6. C++ code:函数指针参数

    函数指针除了进行参数传递外,还承接申请的存储空间.释放空间等.而函数指针则主要是用来进行参数传递的,就像引用一样. 例如,我们来看一下函数指针的传递工作.在标准排序算法sort中,对于所提的整数容器v ...

  7. system

    system("cls"); //清屏 system("color f2") //改变控制台颜色 f2为颜色样式,可以是e2.f3等等 Original:htt ...

  8. hdu5646数学构造+二分

    /* 满足n>=(k+1)*k/2的整数n必定满足 a+(a+1)+...+(a+k-1)<=n<=(a+1)+(a+2)+...+(a+k) 只要在[a,a+k]中减掉一个数字ai ...

  9. python 全栈开发,Day63(子查询,MySQl创建用户和授权,可视化工具Navicat的使用,pymysql模块的使用)

    昨日内容回顾 外键的变种三种关系: 多对一: 左表的多 对右表一 成立 左边的一 对右表多 不成立 foreign key(从表的id) refreences 主表的(id) 多对多 建立第三张表(f ...

  10. centOS下单点部署k8s

    Kubernetes 是Google的一种基于容器的开源服务编排解决方案,在我们进行Kubernetes的学习前,为了对Kubernetes的工作有一个大概的认识, 我们需要先安装一个单节点的实例服务 ...