标签:query hup roo The head cstring algo pushd fread
点分治+线段树(过不去)。
把点分治换成DSU ON THE TREE 应该就能过了。
设S为∏(R[i]-L[i]+1),W[i]为(R[i]-L[i]+1)。
假设有一个点u,则它对答案的贡献为∑(disu + disv) * (S / (W[u] * W[v])),条件为u和v的区间有交。
把式子拆开有两个项,分别用线段树维护即可。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cmath>
#include<cstring>
#include<string>
using namespace std;
char gc()
{
static char buf[100000], *p1 = buf, *p2 = buf;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1++;
}
int getnum()
{
int x = 0, f = 1;
char ch = gc();
while (ch < ‘0‘ || ch > ‘9‘) {
if (ch == ‘-‘) f = -1; ch = gc();
}
while (ch >= ‘0‘ && ch <= ‘9‘) {
x = x * 10 + ch - ‘0‘; ch = gc();
}
return x * f;
}
const int N = 100010, up = 100000, mo = 1e9 + 7;
int n, P;
int cnt;
int head[N];
struct edge
{
int v, nxt;
} vec[N << 1];
int L[N];
int R[N];
int G[N];
int ksm(int a, int b)
{
int s = 1;
while (b) {
if (b & 1) s = 1LL * s * a % mo;
a = 1LL * a * a % mo; b >>= 1;
}
return s;
}
int add(int a, int b)
{
a += b;
if (a >= mo) a -= mo;
if (a < 0) a += mo;
return a;
}
pair<int, int> operator + (pair<int, int> a, pair<int, int> b)
{
return make_pair(add(a.first, b.first), add(a.second, b.second));
}
struct SEG
{
#define lson (o << 1)
#define rson (o << 1 | 1)
int sum[N << 2];
int flag[N << 2];
int ss[N << 2];
int hh[N << 2];
void pushup(int o)
{
sum[o] = add(sum[lson], sum[rson]);
ss[o] = add(ss[lson], ss[rson]);
}
void pushdown(int o, int l, int r)
{
if (flag[o]) {
flag[lson] = add(flag[lson], flag[o]);
flag[rson] = add(flag[rson], flag[o]);
int mid = (l + r) >> 1;
sum[lson] = add(sum[lson], 1LL * flag[o] * (mid - l + 1) % mo);
sum[rson] = add(sum[rson], 1LL * flag[o] * (r - mid) % mo);
flag[o] = 0;
}
if (hh[o]) {
hh[lson] = add(hh[lson], hh[o]);
hh[rson] = add(hh[rson], hh[o]);
int mid = (l + r) >> 1;
ss[lson] = add(ss[lson], 1LL * hh[o] * (mid - l + 1) % mo);
ss[rson] = add(ss[rson], 1LL * hh[o] * (r - mid) % mo);
hh[o] = 0;
}
}
void modify(int o, int l, int r, int L, int R, int p, int v)
{
if (L <= l && r <= R) {
flag[o] = add(flag[o], p); sum[o] = add(sum[o], 1LL * p * (r - l + 1) % mo);
hh[o] = add(hh[o], v); ss[o] = add(ss[o], 1LL * v * (r - l + 1) % mo);
return;
}
pushdown(o, l, r);
int mid = (l + r) >> 1;
if (L <= mid) modify(lson, l, mid, L, R, p, v);
if (R > mid) modify(rson, mid + 1, r, L, R, p, v);
pushup(o);
}
pair<int, int> query(int o, int l, int r, int L, int R)
{
if (L <= l && r <= R) return make_pair(sum[o], ss[o]);
pushdown(o, l, r);
int mid = (l + r) >> 1;
pair<int, int> ret = make_pair(0, 0);
if (L <= mid) ret = ret + query(lson, l, mid, L, R);
if (R > mid) ret = ret + query(rson, mid + 1, r, L, R);
pushup(o);
return ret;
}
void output()
{
for (int i = 1; i <= 20; ++i) printf("%d ", hh[i]); printf("\n");
for (int i = 1; i <= 20; ++i) printf("%d ", ss[i]); printf("\n\n");
}
} SEG;
int S, rt, minn;
int ans;
int siz[N];
bool vis[N];
void addedge(int u, int v)
{
vec[++cnt] = (edge){v, head[u]}; head[u] = cnt;
}
void get_read()
{
n = getnum();
for (int i = 1; i <= n; ++i) L[i] = getnum(), R[i] = getnum();
for (int i = 1; i <= n - 1; ++i) {
int u = getnum(), v = getnum();
addedge(u, v); addedge(v, u);
}
}
void getroot(int u, int fa)
{
int ret = 0; siz[u] = 1;
for (int i = head[u]; i; i = vec[i].nxt) {
int v = vec[i].v;
if (v == fa || vis[v]) continue;
getroot(v, u);
siz[u] += siz[v];
ret = max(ret, siz[v]);
}
ret = max(ret, S - siz[u]);
if (ret < minn) minn = ret, rt = u;
}
void pd(int u, int fa, int w)
{
pair<int, int> X = SEG.query(1, 1, up, L[u], R[u]);
ans = add(ans, 1LL * G[u] % mo * P % mo * add(1LL * X.second * w % mo, X.first) % mo);
for (int i = head[u]; i; i = vec[i].nxt) {
int v = vec[i].v;
if (v == fa || vis[v]) continue;
pd(v, u, w + 1);
}
}
void solve(int u, int fa, int w, int c)
{
SEG.modify(1, 1, up, L[u], R[u], 1LL * c * w % mo * G[u] % mo, 1LL * c % mo * G[u] % mo);
for (int i = head[u]; i; i = vec[i].nxt) {
int v = vec[i].v;
if (v == fa || vis[v]) continue;
solve(v, u, w + 1, c);
}
}
void calc(int u)
{
for (int i = head[u]; i; i = vec[i].nxt) {
int v = vec[i].v;
if (vis[v]) continue;
pd(v, u, 1); solve(v, u, 1, 1);
}
ans = add(ans, 1LL * SEG.query(1, 1, up, L[u], R[u]).first * P % mo * G[u] % mo);
for (int i = head[u]; i; i = vec[i].nxt) {
int v = vec[i].v;
if (vis[v]) continue;
solve(v, u, 1, -1);
}
}
void divide(int u)
{
vis[u] = true; calc(u);
for (int i = head[u]; i; i = vec[i].nxt) {
int v = vec[i].v;
if (vis[v]) continue;
S = siz[v]; rt = v; minn = siz[v];
getroot(v, u); divide(rt);
}
}
void get_work()
{
P = 1;
for (int i = 1; i <= n; ++i) {
P = 1LL * P * (R[i] - L[i] + 1) % mo;
G[i] = ksm(R[i] - L[i] + 1, mo - 2);
}
S = n; rt = 1; minn = n;
getroot(1, 0);
divide(rt);
printf("%d", (ans % mo + mo) % mo);
}
signed main()
{
get_read();
get_work();
return 0;
}
标签:query hup roo The head cstring algo pushd fread
原文地址:https://www.cnblogs.com/calvin99/p/12037682.html