神题。。。std丑的不行。

我们可以发现i->i+1的边被覆盖过i×(n-i)次。

因为以1->i为左端点,以i+1->n的为右端点,i->i+1都将被覆盖这么多次。

然后从1->n扫,i->i+1的路径上的边的贡献就是n×(n-i)×边数-路径上的标记和×(n-i)。因为标记的意义就是它最后一次被覆盖是什么时候。如果tag是k,那么之前1->k为左端点就都统计过这个了。所以就要减标记和×(n-i)(由上面的话可知是n-i次),然后在路径上上打大小为i的tag。具体实现就是树剖+线段树。(我的树剖是直接粘的板子。。。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<algorithm>
#include<cstdlib>
using namespace std;
const int N=;
int n,m,r,a[N],head[N],ecnt,siz[N],fa[N],dep[N],son[N],dfn1[N],dfn2[N],top[N],ncnt,rnk[N];
struct Segtree {
int sum,lazy,l,r;
} seg[N<<];
struct Edge {
int to,nxt;
} e[N<<];
inline void pushup(int x) {
seg[x].sum=seg[x<<].sum+seg[x<<|].sum; }
inline void add(int bg,int ed){
e[++ecnt].nxt=head[bg];
e[ecnt].to=ed;
head[bg]=ecnt;
}
void build(int L,int R,int x) {
seg[x].l=L,seg[x].r=R;
if(L==R) {
seg[x].sum=a[rnk[L]];
return;
}
int mid=(L+R)>>;
build(L,mid,x<<);
build(mid+,R,x<<|);
pushup(x);
} inline void pushdown(int x) {
if(seg[x].lazy) {
if(seg[x].l!=seg[x].r) {
seg[x<<].sum=seg[x].lazy*(seg[x<<].r-seg[x<<].l+); seg[x<<|].sum=(seg[x].lazy)*(seg[x<<|].r-seg[x<<|].l+); seg[x<<].lazy=seg[x].lazy; seg[x<<|].lazy=seg[x].lazy; }
seg[x].lazy=;
}
}
void update(int L,int R,int x,int c) {
if(R<seg[x].l||L>seg[x].r)return;
if(L<=seg[x].l&&seg[x].r<=R) {
seg[x].lazy=c;
seg[x].sum=(seg[x].r-seg[x].l+)*c; return;
}
pushdown(x);
update(L,R,x<<,c);
update(L,R,x<<|,c);
pushup(x);
}
int query(int L,int R,int x){
if(L>seg[x].r||R<seg[x].l)return ;
if(L<=seg[x].l&&seg[x].r<=R){
return seg[x].sum;
}
pushdown(x);
return (query(L,R,x<<)+query(L,R,x<<|));
}
void dfs1(int x){
siz[x]=;
for(int i=head[x];i;i=e[i].nxt){
int v=e[i].to;
if(fa[x]==v) continue;
fa[v]=x;
dep[v]=dep[x]+;
dfs1(v);
siz[x]+=siz[v];
if(siz[v]>siz[son[x]]) son[x]=v;
}
}
void dfs2(int x,int qtop){
top[x]=qtop;dfn1[x]=++ncnt;
rnk[dfn1[x]]=x;
if(son[x]) dfs2(son[x],qtop);
for(int i=head[x];i;i=e[i].nxt){
int v=e[i].to;
if(v==fa[x]||v==son[x]) continue;
dfs2(v,v);
}
dfn2[x]=ncnt;
}
void add_v(int x,int y,int z){
int f1=top[x],f2=top[y];
while(f1!=f2){
if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
update(dfn1[f1],dfn1[x],,z);
x=fa[f1],f1=top[x];
}
if(dep[x]>dep[y]) update(dfn1[y],dfn1[x],,z);
else update(dfn1[x],dfn1[y],,z);
}
inline int query_path(int x,int y){
int f1=top[x],f2=top[y],ans=;
while(f1!=f2){
if(dep[f1]<dep[f2]) swap(f1,f2),swap(x,y);
ans+=query(dfn1[f1],dfn1[x],);
x=fa[f1],f1=top[x];
}
if(dep[x]>dep[y]) ans+=query(dfn1[y],dfn1[x],);
else ans+=query(dfn1[x],dfn1[y],);
return ans;
}
inline int LCA(int x,int y){
while(top[x]!=top[y])
(dep[top[x]]>=dep[top[y]])? x=fa[top[x]]:y=fa[top[y]];;
return dep[x]<dep[y]?x:y;
}
signed main() {
cin>>n;
int u,v,b,c;
for(int i=;i<n;i++){
scanf("%d%d",&u,&v);
add(u,v);
add(v,u);
}
dfs1();
dfs2(,);
build(,n,);
long long ans=;
for(int i=,lca;i<n;i++) {
lca=LCA(i,i+);
ans+=(1ll*(dep[i]-dep[lca]+dep[i+]-dep[lca])*(n-i)*i-1ll*(query_path(i,i+)-query_path(lca,lca))*(n-i));
int tp=query_path(lca,lca);
add_v(i,i+,i);add_v(lca,lca,tp);
}
cout<<ans<<endl;
return ;
}

树上统计

[SDFZOJ]1069:树上统计的更多相关文章

  1. [洛谷U40581]树上统计treecnt

    [洛谷U40581]树上统计treecnt 题目大意: 给定一棵\(n(n\le10^5)\)个点的树. 定义\(Tree[l,r]\)表示为了使得\(l\sim r\)号点两两连通,最少需要选择的边 ...

  2. NOIP2016天天爱跑步 题解报告【lca+树上统计(桶)】

    题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 nn个 ...

  3. Luogu P2664 树上游戏 dfs+树上统计

    题目: P2664 树上游戏 分析: 本来是练习点分治的时候看到了这道题.无意中发现题解中有一种方法可以O(N)解决这道题,就去膜拜了一下. 这个方法是,假如对于某一种颜色,将所有这种颜色的点全部删去 ...

  4. HDU 6043:Colorful Tree(树上统计所有路径总颜色数)***

    题目链接 题意 给出一棵有n个结点的树,每个结点有一个颜色,问在这棵树的所有路径中,每条路径的颜色数求和是多少. 思路 求每种颜色的贡献可以转化为总的和减去每种颜色在哪些路径上没有出现的贡献,一个颜色 ...

  5. 【csp模拟赛6】树上统计-启发式合并,线段树合并

    30%:暴力 40%:枚举L,R从L~n枚举,R每增大一个,更新需要的边(bfs实现)60%:枚举每条边, 计算每条边的贡献另外20%的数据:枚举每条边,计算每条边的贡献100%:对于每一条边统计 有 ...

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

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

  7. 【CF500D】New Year Santa Network(树上统计)

    ..]of longint; z:..]of extended; n,i,m,tot,x1:longint; ans,fenmu,y1:extended; procedure add(a,b:long ...

  8. [hdu5593 ZYB's Tree] 树上统计

    题意:给1棵N(≤500,000)个节点的树,每条边边权为1,求距离每个点距离不超过K(K≤10)的点的个数的xor和. 思路:由于K很小,可以考虑把距离作为状态的一部分,然后研究父子之间状态的联系. ...

  9. EOJ 306 树上问题

    题解: 因为w大于1,所以,题意就是,有多少(x,z),存在x到z的路径上,有一个x<y<z的y w没用的其实. 树上路径问题,有什么方法吗? 1.树链剖分.这个主要方便处理修改操作. 2 ...

随机推荐

  1. 最小生成树模板(poj3625)

    Building Roads Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 9360   Accepted: 2690 De ...

  2. MySql免安装版l配置方法

    初次接触mysql,折腾了一天,总是安装不成功,服务启动不了.后来从官网下载了ZIP Archive版,不用安装,直接把它解压到磁盘,做一些简单的配置就可以. 软件下载地址:http://dev.my ...

  3. scikit-learn:通过Non-negative matrix factorization (NMF or NNMF)实现LSA(隐含语义分析)

    之前写过两篇文章.各自是 1)矩阵分解的综述:scikit-learn:2.5.矩阵因子分解问题 2)关于TruncatedSVD的简介:scikit-learn:通过TruncatedSVD实现LS ...

  4. HDU1573 X问题【一元线性同余方程组】

    题目链接: http://acm.hdu.edu.cn/showproblem.php? pid=1573 题目大意: 求在小于等于N的正整数中有多少个X满足:X mod a[0] = b[0], X ...

  5. ExtJs 给grid某一单元格重新赋值

    // 司机,搬运工提成 var commissionMoney = (waybillsFtQty * commissionMoneyRatio / personCount).toFixed(2); / ...

  6. CentOS-6.5安装配置Tomcat-7

    https://my.oschina.net/u/593517/blog/304483 http://blog.csdn.net/lgh0824/article/details/51194116 摘要 ...

  7. Android+Jquery Mobile学习系列(4)-页面转场及参数传递

    关于页面转场,这个必须得专门列出来说明一下,因为Jquery Mobile与普通的Web发开有一些区别,这个对于新手如果不了解的话,就会钻到死胡同.撸主前段时间就是很急躁地上手开发程序,结果在页面转场 ...

  8. C# 手动编写 DataSet,DataTable 及遍历DataSet中的数据

    一.手动编写DataSet:    有时候不想从数据库导出 DataSet,或者有其他的需要,要将数据库里的DataSet包装成另一个样子,这个时候,了解DataSet的内部结构就非常必要.DataS ...

  9. RMAN 备份与恢复 实例

    1. 检查数据库模式:    sqlplus /nolog     conn /as sysdba    archive log list (查看数据库是否处于归档模式中) 若为非归档,则修改数据库归 ...

  10. P2932 [USACO09JAN]地震造成的破坏Earthquake Damage 爆搜

    这题怎么这么水~~~本来以为挺难的一道题,结果随便一写就过了...本来还不知道损坏的牛棚算不算,结果不明不白就过了... 题干: 农夫John的农场遭受了一场地震.有一些牛棚遭到了损坏,但幸运地,所有 ...