[SDFZOJ]1069:树上统计
神题。。。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:树上统计的更多相关文章
- [洛谷U40581]树上统计treecnt
[洛谷U40581]树上统计treecnt 题目大意: 给定一棵\(n(n\le10^5)\)个点的树. 定义\(Tree[l,r]\)表示为了使得\(l\sim r\)号点两两连通,最少需要选择的边 ...
- NOIP2016天天爱跑步 题解报告【lca+树上统计(桶)】
题目描述 小c同学认为跑步非常有趣,于是决定制作一款叫做<天天爱跑步>的游戏.«天天爱跑步»是一个养成类游戏,需要玩家每天按时上线,完成打卡任务. 这个游戏的地图可以看作一一棵包含 nn个 ...
- Luogu P2664 树上游戏 dfs+树上统计
题目: P2664 树上游戏 分析: 本来是练习点分治的时候看到了这道题.无意中发现题解中有一种方法可以O(N)解决这道题,就去膜拜了一下. 这个方法是,假如对于某一种颜色,将所有这种颜色的点全部删去 ...
- HDU 6043:Colorful Tree(树上统计所有路径总颜色数)***
题目链接 题意 给出一棵有n个结点的树,每个结点有一个颜色,问在这棵树的所有路径中,每条路径的颜色数求和是多少. 思路 求每种颜色的贡献可以转化为总的和减去每种颜色在哪些路径上没有出现的贡献,一个颜色 ...
- 【csp模拟赛6】树上统计-启发式合并,线段树合并
30%:暴力 40%:枚举L,R从L~n枚举,R每增大一个,更新需要的边(bfs实现)60%:枚举每条边, 计算每条边的贡献另外20%的数据:枚举每条边,计算每条边的贡献100%:对于每一条边统计 有 ...
- 树上统计treecnt(dsu on tree 并查集 正难则反)
题目链接 dalao们怎么都写的线段树合并啊.. dsu跑的好慢. \(Description\) 给定一棵\(n(n\leq 10^5)\)个点的树. 定义\(Tree[L,R]\)表示为了使得\( ...
- 【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 ...
- [hdu5593 ZYB's Tree] 树上统计
题意:给1棵N(≤500,000)个节点的树,每条边边权为1,求距离每个点距离不超过K(K≤10)的点的个数的xor和. 思路:由于K很小,可以考虑把距离作为状态的一部分,然后研究父子之间状态的联系. ...
- EOJ 306 树上问题
题解: 因为w大于1,所以,题意就是,有多少(x,z),存在x到z的路径上,有一个x<y<z的y w没用的其实. 树上路径问题,有什么方法吗? 1.树链剖分.这个主要方便处理修改操作. 2 ...
随机推荐
- RPC通信功能实现
Table of Contents RPC通信功能实现 配置參数 调用方法 RPC通信功能实现 HBase的RPC通信功能主要基于Protobuf和NIO这两个组件来实现.在通信管道上选择的是prot ...
- swift 拼图小游戏
依据这位朋友的拼图小游戏改编 http://tangchaolizi.blog.51cto.com/3126463/1571616 改编主要地方是: 原本着我仁兄的代码时支持拖动小图块来移动的,我參照 ...
- linux网络測试命令
ping 192.168.1.103 -c 3 ping我的IP3次 port探測 telnet 192.168.1.103 80 路由跟踪 traceroute www.imooc.co ...
- 使用同步适配器(sync adapter)数据传输
在android设备与webserver之间实现数据同步能显著提高你的应用的有用性.让你的应用更受用户的欢迎. 比方说.你的数据上传给webserver,这就有了一个有用的备份.当用户的设备离线工作时 ...
- 【数据结构】链式向前星知识点&代码
代码: struct NODE{ int to; int nxt; int c; }node[MM];//链式向前星 ; void add(int a,int b,int c){ node[lcnt] ...
- SQL Server 2005数据库定期备份(非常详细)与 SQL Server 2005数据库备份定期清理
SQL Server 2005数据库定期备份 分类: SQL Server 20052011-01-06 16:25 3320人阅读 评论(1) 收藏 举报 sql server数据库sqlserv ...
- B1607 [Usaco2008 Dec]Patting Heads 轻拍牛头 数学
今天净做水题了,这个题还不到十五分钟就搞定了,思路特别简单,就是直接按照线性求因子个数的思路就行了. 题干: Description 今天是贝茜的生日,为了庆祝自己的生日,贝茜邀你来玩一个游戏. 贝茜 ...
- [Swift]实现优先队列PriorityQueue
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs. ...
- 自学Python四 爬虫基础知识储备
首先,推荐两个关于python爬虫不错的博客:Python爬虫入门教程专栏 和 Python爬虫学习系列教程 .写的都非常不错,我学习到了很多东西!在此,我就我看到的学到的进行总结一下! 爬虫就是 ...
- spring事务回滚问题
刚刚接到一个上家公司同事的一个电话,问我为什么service方法事务不会滚了,日志打印了,调用webservice报错. 我让他把这个调用执行webservice的方法截图发给我,如下: publ ...