bzoj3127/3697 [Usaco2013 Open]Yin and Yang

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3127

http://www.lydsy.com/JudgeOnline/problem.php?id=3697

【题解】

点分治。

f[i,0/1]表示前面一坨路径和为i,是否存在休息站。

分类讨论:休息站在点分的地方,休息站在前面子树,休息站在当前子树

子树合并的时候顺便算一发贡献即可。

# include <stdio.h>
# include <string.h>
# include <algorithm>
// # include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
const int M = 5e5 + 10;
const int mod = 1e9+7;

# define RG register
# define ST static

int n; ll ans = 0;
int head[M], nxt[M], to[M], w[M], tot=0;
bool vis[M]; 

inline void add(int u, int v, int _w) {
    ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v; w[tot] = _w;
}
inline void adde(int u, int v, int _w) {
    add(u, v, _w); add(v, u, _w);
}

int sz[M], mx[M];
inline void dfsSize(int x, int fa = 0) {
    sz[x] = 1; mx[x] = 0;
    for (int i=head[x]; i; i=nxt[i]) {
        if(to[i] == fa || vis[to[i]]) continue;
        dfsSize(to[i], x);
        sz[x] += sz[to[i]];
        if(sz[to[i]] > mx[x]) mx[x] = sz[to[i]];
    }
}

int centre = 0, mi;
inline void dfsCentre(int x, int tp, int fa = 0) {
    if(sz[tp] - sz[x] > mx[x]) mx[x] = sz[tp] - sz[x];
    if(mx[x] < mi) mi = mx[x], centre = x;
    for (int i=head[x]; i; i=nxt[i]) {
        if(to[i] == fa || vis[to[i]]) continue;
        dfsCentre(to[i], tp, x);
    }
}

int t[M];
ll f[M][2], g[M][2];
int mxd, vmin = 1e9, vmax = 0;
// g: cur tree, f: all
inline void dfsAns(int x, int v, int fa) {
    if(t[v]) g[v][1] ++;
    else g[v][0] ++;
    t[v] ++;
    vmin = min(vmin, v), vmax = max(vmax, v);
    for (int i=head[x]; i; i=nxt[i]) {
        if(to[i] == fa || vis[to[i]]) continue;
        dfsAns(to[i], v+w[i], x);
    }
    t[v] --;
}

inline void calcAns(int x) {
    int Vmin = 1e7, Vmax = 0;
    f[n][0] = 1;
    for (int i=head[x]; i; i=nxt[i]) {
        if(vis[to[i]]) continue;
        vmin = 1e7, vmax = 0;
        dfsAns(to[i], n+w[i], x);
        Vmin = min(Vmin, vmin), Vmax = max(Vmax, vmax);
        ans += (f[n][0]-1) * g[n][0]; //啥都不动,没有1,是没有意义的,为了计数方便,前面先赋值1.
        for (int j=vmin-n; j<=vmax-n; ++j)
            // 将g合并到f上,统计答案
            ans += f[n-j][1] * g[n+j][1] + f[n-j][0] * g[n+j][1] + f[n-j][1] * g[n+j][0];
        for (int j=vmin; j<=vmax; ++j) {
            f[j][0] += g[j][0];
            f[j][1] += g[j][1];
            g[j][0] = g[j][1] = 0;
        }
    }
    for (int j=Vmin; j<=Vmax; ++j) f[j][0] = f[j][1] = 0;
}

inline void dfs(int x) {
    dfsSize(x);
    mi = n; dfsCentre(x, x);
    // cross the centre
    calcAns(centre);
    // ================
    vis[centre] = 1;
    for (int i=head[centre]; i; i=nxt[i]) {
        if(!vis[to[i]]) dfs(to[i]);
    }
}

int main() {
    scanf("%d", &n);
    for (int i=1; i<n; ++i) {
        int u, v, _w; scanf("%d%d%d", &u, &v, &_w);
        adde(u, v, _w ? 1 : -1);
    }
    dfs(1);
    printf("%lld\n", ans);
    return 0;
}

把0/1记录1/-1会方便很多啊不过注意下标+n

时间: 2024-10-08 21:58:03

bzoj3127/3697 [Usaco2013 Open]Yin and Yang的相关文章

BZOJ 3127:[Usaco2013 Open]Yin and Yang(树点分治)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3127 [题目大意] 给出一棵01边权树,求存在多少条路径,使得路径上0和1的数量相同, 并且在路劲中能找到至少一个中断点,使得分为两段01数量相同的路径 [题解] 我们对这棵树进行点分治,每次只考虑经过重心的路径, 我们将路径权值和分出现一次和出现多次进行统计,如果出现一次, 则在之前出现了多次的权值数组中查相反数,如果出现多次, 则是一次和多次的权值数组的和,权值和为0的特殊情况则

【BZOJ】【3697】采药人的路径 &amp; 【3127】【USACO2013 Open】Yin and Yang

点分治 Orz hzwer 倒是比较好想到点分治……然而在方案统计这里,我犯了两个错误…… 1.我比较傻逼的想的是:通过儿子来更新父亲,也就是统计以x为根的子树中xxxx的路径有多少条……这样转移. 然而这实在是太傻逼了,黄学长教做人:从父亲来更新儿子,走到一个节点直接更新路径的统计数,反正我们要的是[经过root的xx路径的数量] 所以可以一遍dfs直接搞出来…… 2.统计方案的方式也想错了……我只考虑了以root作为中转站的路径,然而经过root的路径中,并不只有这种路径是合法的……中转站在

Yin and Yang Stones(思路题)

Problem Description: A mysterious circular arrangement of black stones and white stones has appeared. Ming has been tasked with balancing the stones so that only one black and one white stone remain. Ming has two operations for balancing the stones:

【BZOJ-3697&amp;3127】采药人的路径&amp;YinandYang 点分治 + 乱搞

3697: 采药人的路径 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 681  Solved: 246[Submit][Status][Discuss] Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动.他选择的路径是很有讲究的,他认为阴阳平衡是很重要的,所以他走的一定是两种药材数目相等的路径.

XVII Open Cup named after E.V. Pankratiev. Grand Prix of America (NAIPC-2017)

A. Pieces of Parentheses 将括号串排序,先处理会使左括号数增加的串,这里面先处理减少的值少的串:再处理会使左括号数减少的串,这里面先处理差值较大的串.确定顺序之后就可以DP了. 时间复杂度$O(n^3)$. #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N=310,inf=1000000; int n,i,j,m,all,

blade and soul races guide

Race Four races are available for those who wish to choose the path of martial arts: the careful Gon, the playful Lyn, the elegant Yun, and the hardworking Jin. Blade & Soulcontains four playable races. They consist of the powerful Gon, the ambitious

Apply Functional Programming Principles

Apply Functional Programming Principles Edward Garson FUNCTiONAL PROGRAMMiNG has recently enjoyed renewed interest from the mainstream programming community. Part of the reason is because emergent properties of the functional paradigm are well positi

hdu 5727 二分图+环排列

Necklace Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2423    Accepted Submission(s): 766 Problem Description SJX has 2*N magic gems. N of them have Yin energy inside while others have Yang e

hdu 5727 Necklace 阴阳珠 二分图匹配+暴力全排列

Necklace Time Limit: 3000/1500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 2462    Accepted Submission(s): 775 Problem Description SJX has 2*N magic gems. N of them have Yin energy inside while others have Yang e