题目大意

一棵树,每个节点的权为L[i]~R[i],一棵树的贡献为\(\sum\limits_{h_{i} = h_{j}, 1 \le i < j \le n}{dis(i,j)}\),其中\(dis(i,j)\)表示i到j路径上的边数

求\(\prod\limits_{i = 1}^{n} (r_{i} - l_{i} + 1)\)种不同取值的情况的贡献和

题解

一眼点分治

把一个点的子树上除该点的乘积加到对应区间上,查找就直接找对应区间

设S[i]表示\(\prod_{i\neq j}{R_i-L_i+1}\),W[i]表示\(\frac{1}{R_i-L_i+1}\)

那么在b点查询a时一种方案的贡献为\(S[a]*W[b]*(dis[a]+dis[b])\),拆开后为\(W[b]*S[a]*dis[a]+W[b]*dis[b]*S[a]\),维护S[a]*dis[a]与S[a]的和即可

线段树常数较大,所以要用树状数组

code

#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstring>
#include <cstdio>
#define fo(a,b,c) for (a=b; a<=c; a++)
#define fd(a,b,c) for (a=b; a>=c; a--)
#define add(a,b) a=((a)+(b))%1000000007
#define max(a,b) (a>b?a:b)
#define low(x) (x&-(x))
#define mod 1000000007
#define Mod 1000000005
#define N 100000
using namespace std; int a[200001][2];
int tr[100001][4];
bool Tr[100001];
int d[100001];
int ls[100001];
int L[100001];
int R[100001];
int size[100001];
bool bz[100001];
int Fa[100001];
long long S[100001];
long long w[100001];
int n,i,j,k,l,len,mn1,mn2,SIZE,tot;
long long sum,ans,W,D,WD,find1,find2; void New(int x,int y)
{
++len;
a[len][0]=y;
a[len][1]=ls[x];
ls[x]=len;
} long long qpower(long long a,int b)
{
long long ans=1; while (b)
{
if (b&1)
ans=ans*a%mod; a=a*a%mod;
b>>=1;
} return ans;
} void Change(int t,long long s1,long long s2)
{
long long S1=-s1*(t-1)%mod,S2=-s2*(t-1)%mod; while (t<=N)
{
if (!Tr[t])
Tr[t]=1,d[++tot]=t; add(tr[t][0],s1);
add(tr[t][1],S1);
add(tr[t][2],s2);
add(tr[t][3],S2); t+=low(t);
}
}
void change(int l,int r,long long s1,long long s2)
{
Change(l,s1,s2);
Change(r+1,-s1,-s2);
} void Find(int t,int type)
{
int T=t; long long s1,S1,s2,S2;
s1=S1=s2=S2=0; while (t)
{
add(s1,tr[t][0]);
add(S1,tr[t][1]);
add(s2,tr[t][2]);
add(S2,tr[t][3]); t-=low(t);
} add(find1,(s1*T+S1)%mod*type);
add(find2,(s2*T+S2)%mod*type);
}
void find(int l,int r)
{
find1=find2=0;
Find(r,1);
Find(l-1,-1);
} void dfs1(int fa,int t)
{
int i,mx=0; Fa[t]=fa;
size[t]=1; for (i=ls[t]; i; i=a[i][1])
if (!bz[a[i][0]] && a[i][0]!=fa)
{
dfs1(t,a[i][0]); size[t]+=size[a[i][0]];
mx=max(mx,size[a[i][0]]);
}
mx=max(mx,SIZE-size[t]); if (mx<mn1)
mn1=mx,mn2=t;
} void dfs2(int fa,int t,int dis)
{
int i; W=w[t];D=dis;WD=W*D%mod; find(L[t],R[t]); add(ans,WD*find1+W*find2); for (i=ls[t]; i; i=a[i][1])
if (!bz[a[i][0]] && a[i][0]!=fa)
dfs2(t,a[i][0],dis+1);
} void dfs3(int fa,int t,int dis)
{
int i; change(L[t],R[t],S[t],S[t]*dis%mod); for (i=ls[t]; i; i=a[i][1])
if (!bz[a[i][0]] && a[i][0]!=fa)
dfs3(t,a[i][0],dis+1);
} void work(int t,int Size)
{
int i; SIZE=Size;
mn1=Size;
mn2=t; dfs1(0,t);
t=mn2;
bz[t]=1; // --- tot=0;
change(L[t],R[t],S[t],0); for (i=ls[t]; i; i=a[i][1])
if (!bz[a[i][0]])
{
dfs2(t,a[i][0],1);
dfs3(t,a[i][0],1);
} fo(i,1,tot)
tr[d[i]][0]=tr[d[i]][1]=tr[d[i]][2]=tr[d[i]][3]=Tr[d[i]]=0; // --- for (i=ls[t]; i; i=a[i][1])
if (!bz[a[i][0]] && a[i][0]!=Fa[t])
work(a[i][0],size[a[i][0]]); if (Fa[t])
work(Fa[t],Size-size[t]);
} int main()
{
// freopen("f.in","r",stdin);
// freopen("b.out","w",stdout); sum=1; scanf("%d",&n);
fo(i,1,n)
scanf("%d%d",&L[i],&R[i]),sum=(sum*(R[i]-L[i]+1))%mod,w[i]=qpower(R[i]-L[i]+1,Mod);
fo(i,2,n)
{
scanf("%d%d",&j,&k); New(j,k);
New(k,j);
} fo(i,1,n)
S[i]=sum*w[i]%mod; work(1,n); printf("%I64d\n",(ans+mod)%mod);
}

CF1260F的更多相关文章

随机推荐

  1. cocos2dx[3.2](1) 浅析cocos2dx3.2引擎目录

    3.x的引擎目录与2.x的引擎目录的差别是非常大的.3.x主要是将引擎的各个文件按照用途进行了分类,使得引擎目录结构更加清晰了. 从目录中我们主要了解一下以下几个文件: 文件名 说明 build 官方 ...

  2. LeetCode.937-重新排序日志数组(Reorder Log Files)

    这是悦乐书的第358次更新,第385篇原创 01 看题和准备 今天介绍的是LeetCode算法题中Easy级别的第220题(顺位题号是937).你有一系列日志.每个日志都是以空格分隔的单词串. 每个日 ...

  3. 【深度聚类】Superpixel Sampling Networks

    Superpixel Sampling Networks 原始文档:https://www.yuque.com/lart/papers/ssn 本文的思想很简单,传统的超像素算法是一种有效的低/中级的 ...

  4. NOIp D1T1 小凯的疑惑

    吐槽 果然让人很疑惑,这道题,对于我这种数学渣渣来说太不友好了,哪里想得到结论,猜也猜不到. 思路一 纯数学,见过的飞快切掉,没见过的就... 结论就是:已知$a,b$为大于$ 1 $的互质的正整数, ...

  5. excel常用公式--时间序列类

    year,month,day:返回对应于某个日期的年月日.Year作为1900 - 9999之间的整数返回. weekday:返回对应于某个日期的一周中的第几天. WEEKNUM:返回特定日期的周数. ...

  6. 2019JAVA第九次实验报告

    Java实验报告 班级 计科二班 学号 20188442 姓名 吴怡君 完成时间 2019.11.8 评分等级 课程总结 1.实验代码 package Domon8; import java.awt. ...

  7. C语言I博客作业12

    一.我学到的内容 二.我的收获 作业链接 收获 博客第一次作业:https://www.cnblogs.com/gm12/p/11584148.html 第一次作业收获:第一次作业是我初步接触C语言的 ...

  8. 洛谷 P1194 飞扬的小鸟 题解

    题面 这道题是一道隐藏的比较深的DP(我太蒟蒻了!) 设f[i][j]表示到第i列时高度为j的最少步数是多少: 求上升时的方案就是一个完全背包!,求下降时的方案就是一个01背包: 然后处理边界就能A掉 ...

  9. array_chunk的用法和php操作大数据

    一.array_chunk() 函数 二.php操作大数据 1.在操作大数量数据与数据库交互时,比如插入大量数据,db就会报错,这时可以把原本的数据用array_chunk分隔成几个数组块,再循环插入 ...

  10. mysql之general log 日志

    开启 general log 将所有到达MySQL Server的SQL语句记录下来. 一般不会开启开功能,因为log的量会非常庞大.但个别情况下可能会临时的开一会儿general log以供排障使用 ...