链接

点击跳转

AC的做法

枚举颜色,然后考虑我可以点亮某个点或者熄灭某个点,以点亮某个点为例,假设这个点是iii,枚举树上已经被点亮的点jjj,那么此时答案的增量为
∑j(depthi+depthj−2depthlca(i,j))wiwjP\sum_{j} (depth_i+depth_j-2depth_{lca(i,j)})w_iw_jP j∑​(depthi​+depthj​−2depthlca(i,j)​)wi​wj​P

其中P=∏(ri−li+1),wi=(ri−li+1)−1P = \prod (r_i-l_i+1),w_i = (r_i-l_i+1)^{-1}P=∏(ri​−li​+1),wi​=(ri​−li​+1)−1

化简一下得到
Pwi(depthi∑jdepthj+∑jwjdepthj−2∑jdepthlca(i,j)wj)P w_i \left( depth_i \sum_{j} depth_j + \sum_{j} w_j depth_j - 2 \sum_{j} depth_{lca(i,j)}w_j \right) Pwi​(depthi​j∑​depthj​+j∑​wj​depthj​−2j∑​depthlca(i,j)​wj​)

一共三项,前两项都很容易维护

第三项,我可以对于已存在的jjj,把根节点到jjj的每个节点的权值都+=wj+=w_j+=wj​,那么iii到根节点这条路径上的权值之和就是第三项

AC的代码

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 100010
#define maxe 200010
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
#define mod 1000000007ll
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{ll c, f(1);for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;for(;isdigit(c);c=getchar())x=x*10+c-0x30;return f*x;
}
ll ans, n, l[maxn], r[maxn], inv[maxn], P, now, w[maxn];
struct SegmentTree
{ll sum[maxn<<2], add[maxn<<2], set[maxn<<2], L[maxn<<2], R[maxn<<2];void maketag_set(ll o, ll v){add[o]=0;set[o]=v;sum[o]=(R[o]-L[o]+1)*v;}void maketag_add(ll o, ll v){(add[o]+=v)%=mod;(sum[o]+=(R[o]-L[o]+1)*v)%=mod;}void pushdown(ll o){if(L[o]==R[o])return;if(~set[o]){maketag_set(o<<1,set[o]);maketag_set(o<<1|1,set[o]);set[o]=-1;}if(add[o]){maketag_add(o<<1,add[o]);maketag_add(o<<1|1,add[o]);add[o]=0;}}void pushup(ll o){(sum[o]=sum[o<<1]+sum[o<<1|1])%mod;}void build(ll o, ll l, ll r){ll mid(l+r>>1);L[o]=l, R[o]=r;add[o]=0;set[o]=-1;if(l==r){return;}build(o<<1,l,mid);build(o<<1|1,mid+1,r);pushup(o);}void segset(ll o, ll l, ll r, ll v){ll mid(L[o]+R[o]>>1);if(l<=L[o] and r>=R[o]){maketag_set(o,v);return;}pushdown(o);if(l<=mid)segset(o<<1,l,r,v);if(r>mid)segset(o<<1|1,l,r,v);pushup(o);}void segadd(ll o, ll l, ll r, ll v){ll mid(L[o]+R[o]>>1);if(l<=L[o] and r>=R[o]){maketag_add(o,v);return;}pushdown(o);if(l<=mid)segadd(o<<1,l,r,v);if(r>mid)segadd(o<<1|1,l,r,v);pushup(o);}ll segsum(ll o, ll l, ll r){pushdown(o);ll mid(L[o]+R[o]>>1), ans(0);if(l<=L[o] and r>=R[o])return sum[o];if(l<=mid)ans+=segsum(o<<1,l,r);if(r>mid)ans+=segsum(o<<1|1,l,r);return ans%mod;}
}segtree;
struct Graph
{int etot, head[maxn], to[maxe], next[maxe], w[maxe];void clear(int N){for(int i=1;i<=N;i++)head[i]=0;etot=0;}void adde(int a, int b, int c=0){to[++etot]=b;w[etot]=c;next[etot]=head[a];head[a]=etot;}#define forp(pos,G) for(auto p=G.head[pos];p;p=G.next[p])
}G;
struct Heavy_Light_Decomposition
{int size[maxn], top[maxn], tid[maxn], tim, untid[maxn], depth[maxn], son[maxn], fa[maxn];void dfs1(Graph &G, int pos){int p, v;size[pos]=1;for(p=G.head[pos];p;p=G.next[p]){if((v=G.to[p])==fa[pos])continue;fa[v]=pos;depth[v]=depth[pos]+1;dfs1(G,v);if(size[v]>size[son[pos]])son[pos]=v;size[pos]+=size[v];}}void dfs2(Graph &G, int pos, int tp){int p, v;top[pos]=tp;tid[pos]=++tim;untid[tid[pos]]=pos;if(son[pos])dfs2(G,son[pos],tp);for(p=G.head[pos];p;p=G.next[p])if((v=G.to[p])!=fa[pos] and v!=son[pos])dfs2(G,v,v);}void run(Graph &G, int root){tim=0;depth[root]=1;dfs1(G,root);dfs2(G,root,root);}
}HLD;
vector<pll> events[maxn];
int main()
{ll n, i;inv[1]=1;for(int i=2;i<maxn;i++)inv[i]=inv[mod%i]*(mod-mod/i)%mod;n=read();P=1;rep(i,n){l[i]=read(), r[i]=read();(P*=r[i]-l[i]+1)%=mod;w[i]=inv[r[i]-l[i]+1];events[l[i]].emb( pll(i,+1) );events[r[i]+1].emb( pll(i,-1) );}rep(i,n-1){int u=read(), v=read();G.adde(u,v), G.adde(v,u);}HLD.run(G,1);segtree.build(1,1,n);ll sw=0, sdw=0;rep(i,1e5){for(auto e:events[i]){auto pos=e.fi, v=e.se;ll delt=0;(delt += HLD.depth[pos]*sw)%=mod;(delt += sdw)%=mod;ll s=0, x=pos;while(x){auto tp = HLD.top[x];(s+=segtree.segsum(1,HLD.tid[tp],HLD.tid[x]))%=mod;x=HLD.fa[tp];}(delt -= 2*s)%=mod;(now+=v*P*w[pos]%mod*delt)%=mod;x=pos;while(x){auto tp = HLD.top[x];segtree.segadd(1,HLD.tid[tp],HLD.tid[x],w[pos]*v);x=HLD.fa[tp];}(sw+=v*w[pos])%=mod;(sdw+=v*w[pos]*HLD.depth[pos])%=mod;}(ans+=now)%=mod;}cout<<(ans+mod)%mod;return 0;
}

因为常数太大而TLETLETLE的做法

点分治,一棵子树一棵子树的进行合并

新来一棵子树的时候,我就对于每个节点都求一下它颜色区间的深度和,这是路径的一段,另一段可以通过维护每种颜色被多少个点包含了进而算出来

两个线段树可能常数比较大?
而且实际上线段树操作的调用次数也比前一种算法多,所以就TLETLETLE了

因为常数太大而TLETLETLE的代码

#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
#define iinf 0x3f3f3f3f
#define linf (1ll<<60)
#define eps 1e-8
#define maxn 100010
#define maxe 200010
#define maxk 17
#define cl(x) memset(x,0,sizeof(x))
#define rep(_,__) for(_=1;_<=(__);_++)
#define em(x) emplace(x)
#define emb(x) emplace_back(x)
#define emf(x) emplace_front(x)
#define fi first
#define se second
#define de(x) cerr<<#x<<" = "<<x<<endl
#define mod 1000000007ll
using namespace std;
using namespace __gnu_pbds;
typedef long long ll;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
ll read(ll x=0)
{ll c, f(1);for(c=getchar();!isdigit(c);c=getchar())if(c=='-')f=-f;for(;isdigit(c);c=getchar())x=x*10+c-0x30;return f*x;
}
ll ans, n, l[maxn], r[maxn], inv[maxn], P;
struct SegmentTree
{ll sum[maxn<<2], add[maxn<<2], set[maxn<<2], L[maxn<<2], R[maxn<<2];void maketag_set(ll o, ll v){add[o]=0;set[o]=v;sum[o]=(R[o]-L[o]+1)*v;}void maketag_add(ll o, ll v){(add[o]+=v)%=mod;(sum[o]+=(R[o]-L[o]+1)*v)%=mod;}void pushdown(ll o){if(L[o]==R[o])return;if(~set[o]){maketag_set(o<<1,set[o]);maketag_set(o<<1|1,set[o]);set[o]=-1;}if(add[o]){maketag_add(o<<1,add[o]);maketag_add(o<<1|1,add[o]);add[o]=0;}}void pushup(ll o){(sum[o]=sum[o<<1]+sum[o<<1|1])%mod;}void build(ll o, ll l, ll r){ll mid(l+r>>1);L[o]=l, R[o]=r;add[o]=0;set[o]=-1;if(l==r){return;}build(o<<1,l,mid);build(o<<1|1,mid+1,r);pushup(o);}void segset(ll o, ll l, ll r, ll v){ll mid(L[o]+R[o]>>1);if(l<=L[o] and r>=R[o]){maketag_set(o,v);return;}pushdown(o);if(l<=mid)segset(o<<1,l,r,v);if(r>mid)segset(o<<1|1,l,r,v);pushup(o);}void segadd(ll o, ll l, ll r, ll v){ll mid(L[o]+R[o]>>1);if(l<=L[o] and r>=R[o]){maketag_add(o,v);return;}pushdown(o);if(l<=mid)segadd(o<<1,l,r,v);if(r>mid)segadd(o<<1|1,l,r,v);pushup(o);}ll segsum(ll o, ll l, ll r){pushdown(o);ll mid(L[o]+R[o]>>1), ans(0);if(l<=L[o] and r>=R[o])return sum[o];if(l<=mid)ans+=segsum(o<<1,l,r);if(r>mid)ans+=segsum(o<<1|1,l,r);return ans%mod;}
}sum_tree, cnt_tree;
struct Graph
{int etot, head[maxn], to[maxe], next[maxe], w[maxe];void clear(int N){for(int i=1;i<=N;i++)head[i]=0;etot=0;}void adde(int a, int b, int c=0){to[++etot]=b;w[etot]=c;next[etot]=head[a];head[a]=etot;}#define forp(pos,G) for(auto p=G.head[pos];p;p=G.next[p])
}G;
struct Centroid_Decomposition
{ll grey[maxn], depth[maxn], size[maxn], dist[maxn], lis[maxn];void dfs(ll pos, ll pre, Graph& G){lis[++*lis]=pos;// lis.emb(pos);// de(pos);size[pos]=1;forp(pos,G)if(G.to[p]!=pre and !grey[G.to[p]]){depth[G.to[p]]=depth[pos]+1;dist[G.to[p]]=dist[pos]+G.w[p];dfs(G.to[p],pos,G);size[pos]+=size[G.to[p]];}}void findG(ll pos, ll pre, Graph& G, ll& g, ll& gsum, ll nowsum, ll node_tot){if(nowsum<gsum)g=pos, gsum=nowsum;forp(pos,G)if(G.to[p]!=pre and !grey[G.to[p]])findG( G.to[p], pos, G, g, gsum, nowsum+(node_tot-2*size[G.to[p]]), node_tot );}void solve(ll pos, Graph& G){*lis=0; dfs(pos,0,G);ll g=pos, gsum=0, i;rep(i,*lis)gsum+=depth[lis[i]];//, cerr<<x<<'('<<size[x]<<')'<<' ';cerr<<endl;findG(pos,0,G,g,gsum,gsum,*lis);grey[g]=1;//--- process ---sum_tree.segset(1,1,1e5,0);cnt_tree.segset(1,1,1e5,0);forp(g,G)if(!grey[G.to[p]]){depth[G.to[p]]=1;*lis=0;dfs(G.to[p],g,G);rep(i,*lis){auto x=lis[i];ans += sum_tree.segsum(1,l[x],r[x])*inv[r[x]-l[x]+1]%mod;ans += cnt_tree.segsum(1,l[x],r[x])*depth[x]%mod*inv[r[x]-l[x]+1]%mod;ans%=mod;}rep(i,*lis){auto x=lis[i];sum_tree.segadd(1,l[x],r[x],depth[x]*inv[r[x]-l[x]+1]%mod*P%mod);cnt_tree.segadd(1,l[x],r[x],inv[r[x]-l[x]+1]*P%mod);}}(ans+=sum_tree.segsum(1,l[g],r[g])*inv[r[g]-l[g]+1])%=mod;   //不要忘记处理一端在重心的路径//---------------forp(g,G)if(!grey[G.to[p]])solve(G.to[p],G);}
}CD;
int main()
{int n, i;inv[1]=1;for(int i=2;i<maxn;i++)inv[i]=inv[mod%i]*(mod-mod/i)%mod;n=read();P=1;rep(i,n){l[i]=read(), r[i]=read();(P*=r[i]-l[i]+1)%=mod;}rep(i,n-1){int u=read(), v=read();G.adde(u,v), G.adde(v,u);}// de("debug1");sum_tree.build(1,1,1e5);cnt_tree.build(1,1,1e5);// de("debug2");CD.solve(1,G);cout<<ans;return 0;
}

cf1260 F. Colored Tree相关推荐

  1. Codeforces Round #699 (Div. 2) F - AB Tree(贪心、树上DP)超级清晰,良心题解,看不懂来打我 ~

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 Codeforces Round #699 (Div. 2) F - AB Tree Problem ...

  2. F - Colorful Tree(LCA,树上差分,离线处理)

    F - Colorful Tree 给定一棵树,边有边权,且每条边有一个颜色,有mmm次操作, 每次给定x,y,u,vx, y, u, vx,y,u,v,如果把颜色为xxx的边,边权修改为yyy,求u ...

  3. Codeforces Round #375 (Div. 2) F. st-Spanning Tree 生成树

    F. st-Spanning Tree 题目连接: http://codeforces.com/contest/723/problem/F Description You are given an u ...

  4. CodeCraft-22 and Codeforces Round #795 (Div. 2) F. K-Set Tree

    题目链接 题意 给定一个树,f(r,S)f(r,S)f(r,S) 表示该树以 rrr 为根,节点 VVV 的子集 ∣S∣=k|S|=k∣S∣=k,包含 SSS 的最小子树的大小.求所有 f(r,S)f ...

  5. unix命令的一般格式是_Linux tree 命令详细使用说明

    请关注本头条号,每天坚持更新原创干货技术文章. 如需学习视频,请在微信搜索公众号"智传网优"直接开始自助视频学习 1. 前言 本文主要讲解Linux系统上的tree命令的详细使用方 ...

  6. 二叉排序树(Binary Sort Tree) 又称为二叉查找树(Binary Search Tree) - (代码、分析)

    目录: 代码: 分析: 代码: BSTree.h #ifndef _BSTREE_H_ #define _BSTREE_H_typedef void BSTree;//定义二叉树类型 typedef ...

  7. 机器学习算法实践:决策树 (Decision Tree)(转载)

    前言 最近打算系统学习下机器学习的基础算法,避免眼高手低,决定把常用的机器学习基础算法都实现一遍以便加深印象.本文为这系列博客的第一篇,关于决策树(Decision Tree)的算法实现,文中我将对决 ...

  8. 巧用tree命令导出文件目录递归详情

    缘由 我清楚的记得在我读研二的时候有一次我帮老师收"海外名师课堂"的作业,有一名巴基斯坦的学生,想要老师的课件,我当时给他说这个不被允许,随便给外国留学生拷贝课件原则上是不允许的, ...

  9. 2019牛客全国多校训练三 题解

    A Gragh Games Unsolved. B Crazy Binary String 题解:水题,子序列只要统计0和1数量,取最小值然后乘2就是答案: 对于子串:先记录0和1 前缀和的差值,然后 ...

最新文章

  1. NCBI SRA数据库使用详解
  2. Netty详解(二)Linux 网络IO模型
  3. Java程序员最值得学习的10大技术
  4. 上传图片插件鼠标手cursor:pointer;不生效
  5. dalvik.system.PathClassLoader[DexPathList[[zip file /data/app/comda.xfdsafda.activdity-1/base.apk]
  6. 苹果修复被 XCSSET 恶意软件滥用的3个 0day
  7. 静态include与动态include的区别
  8. HDU-2057(16进制的输入输出)
  9. 使用xcap进行更改报文并进行回放以及回放报文只能看到请求流量看不到响应流量的问题
  10. Java实习日记(3)
  11. P68是什么意思 IP67和IP68等级有什么区别
  12. win10系统跟Linux系统哪个好,Linux比Windows10系统好吗?Linux vs Win10测试
  13. 选购笔记本要看清液晶屏幕及主流技术
  14. jenkins安装了中文插件发现界面还有英文的解决方法
  15. 华为mate40e灭屏显示教程
  16. android ue设计原则,ued设计原则
  17. 同时使用 IE7 和 IE6 的方法
  18. 1.7 JAVA 向上转型和向下转型解析
  19. 大数据----------------R语言下依赖库与依赖包的安装
  20. 亚马逊要求的FCC-ID和 CE-RED认证的定频机是什么

热门文章

  1. 《基于ITK和VTK的医学图像处理系统设计与实现》
  2. HTML5知识点总结(五)
  3. 文件的哈夫曼编码与解码
  4. Springboot、React集成Okta SAML2单点登录
  5. 管家婆软件分销ERP D9学习资料
  6. 我所学到的EC-1(个人学习总结,不能保证正确,欢迎大佬指正)
  7. 计算机组成原理——作业2
  8. 关于组装微型计算机的叙述不正确的是,计算机与交互式白板通过USB数据线物理连接后,还要正确安装(),这样才能正常使用。...
  9. Python——列表推导式
  10. 电子数据取证Windows取证读书笔记