码迷,mamicode.com
首页 > 其他好文 > 详细

CF 1260F colored tree

时间:2019-12-13 23:25:26      阅读:102      评论:0      收藏:0      [点我收藏+]

标签: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;
}

CF 1260F colored tree

标签:query   hup   roo   The   head   cstring   algo   pushd   fread   

原文地址:https://www.cnblogs.com/calvin99/p/12037682.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!