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

点分治



  Orz hzwer

  倒是比较好想到点分治……然而在方案统计这里,我犯了两个错误……

  1.我比较傻逼的想的是:通过儿子来更新父亲,也就是统计以x为根的子树中xxxx的路径有多少条……这样转移。

  然而这实在是太傻逼了,黄学长教做人:从父亲来更新儿子,走到一个节点直接更新路径的统计数,反正我们要的是【经过root的xx路径的数量】

  所以可以一遍dfs直接搞出来……

  2.统计方案的方式也想错了……我只考虑了以root作为中转站的路径,然而经过root的路径中,并不只有这种路径是合法的……中转站在途中某个点的也可以QwQ

  另外感觉黄学长记录[-d,d]的姿势很神啊……直接数组开大一倍,然后转成[n-d,n+d]……

  其他的……套模板呗- -

  1 //BZOJ 3697
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<cstdlib>
  5 #include<iostream>
  6 #include<algorithm>
  7 #define rep(i,n) for(int i=0;i<n;++i)
  8 #define F(i,j,n) for(int i=j;i<=n;++i)
  9 #define D(i,j,n) for(int i=j;i>=n;--i)
 10 #define pb push_back
 11 using namespace std;
 12 typedef long long LL;
 13 inline int getint(){
 14     int r=1,v=0; char ch=getchar();
 15     for(;!isdigit(ch);ch=getchar()) if (ch==‘-‘) r=-1;
 16     for(; isdigit(ch);ch=getchar()) v=v*10-‘0‘+ch;
 17     return r*v;
 18 }
 19 const int N=1e5+10;
 20 /*******************template********************/
 21
 22 int to[N<<1],nxt[N<<1],head[N],cnt,v[N<<1];
 23 void add(int x,int y,int z){
 24     to[++cnt]=y; nxt[cnt]=head[x]; head[x]=cnt; v[cnt]=z;
 25     to[++cnt]=x; nxt[cnt]=head[y]; head[y]=cnt; v[cnt]=z;
 26 }
 27
 28 int n,rt,s[N],h[N],size,dep[N],mxdeep;
 29 LL ans,g[N*2][2],f[N*2][2];
 30 int t[N<<1],dis[N];
 31 bool vis[N];
 32
 33 inline void getroot(int x,int fa){
 34     s[x]=1; h[x]=0;
 35     for(int i=head[x];i;i=nxt[i])
 36         if (to[i]!=fa && !vis[to[i]]){
 37             getroot(to[i],x);
 38             s[x]+=s[to[i]];
 39             h[x]=max(h[x],s[to[i]]);
 40         }
 41     h[x]=max(h[x],size-s[x]);
 42     if (h[x]<h[rt]) rt=x;
 43 }
 44
 45 inline void dfs(int x,int fa){
 46     mxdeep=max(mxdeep,dep[x]);
 47     if (t[dis[x]]) g[dis[x]][1]++;
 48     else g[dis[x]][0]++;
 49     t[dis[x]]++;
 50     for(int i=head[x];i;i=nxt[i])
 51         if (!vis[to[i]] && to[i]!=fa){
 52             dep[to[i]]=dep[x]+1;
 53             dis[to[i]]=dis[x]+v[i];
 54             dfs(to[i],x);
 55         }
 56     t[dis[x]]--;
 57 }
 58 inline void getans(int x){
 59     int mx=0;
 60     vis[x]=1; f[n][0]=1;
 61     for(int i=head[x];i;i=nxt[i])
 62         if (!vis[to[i]]){
 63             dis[to[i]]=n+v[i];
 64             dep[to[i]]=1;
 65             mxdeep=1;
 66             dfs(to[i],x); mx=max(mx,mxdeep);
 67             ans+=(f[n][0]-1)*g[n][0];
 68             F(j,-mxdeep,mxdeep)
 69                 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];
 70             //f[n][0]+1的原因是要将x作为起点or终点的合法路径(g[n][1])统计进来
 71             F(j,n-mxdeep,n+mxdeep)
 72                 f[j][0]+=g[j][0],
 73                 f[j][1]+=g[j][1],
 74                 g[j][0]=g[j][1]=0;
 75         }
 76     F(i,n-mx,n+mx) f[i][0]=f[i][1]=0;
 77     //统计答案↑
 78     for(int i=head[x];i;i=nxt[i])
 79         if (!vis[to[i]]){
 80             rt=0; size=s[to[i]];
 81             getroot(to[i],x);
 82             getans(rt);
 83         }
 84     //继续分治↑
 85 }
 86 int main(){
 87 #ifndef ONLINE_JUDGE
 88     freopen("3697.in","r",stdin);
 89     freopen("3697.out","w",stdout);
 90 #endif
 91     n=getint();
 92     F(i,2,n){
 93         int x=getint(),y=getint(),z=getint();
 94         if (!z) z--;
 95         add(x,y,z);
 96     }
 97     size=n; h[rt=0]=n+1;
 98     getroot(1,0);
 99     getans(rt);
100     printf("%lld\n",ans);
101     return 0;
102 }

3697: 采药人的路径

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 252  Solved: 93
[Submit][Status][Discuss]

Description

采药人的药田是一个树状结构,每条路径上都种植着同种药材。
采药人以自己对药材独到的见解,对每种药材进行了分类。大致分为两类,一种是阴性的,一种是阳性的。
采药人每天都要进行采药活动。他选择的路径是很有讲究的,他认为阴阳平衡是很重要的,所以他走的一定是两种药材数目相等的路径。采药工作是很辛苦的,所以
他希望他选出的路径中有一个可以作为休息站的节点(不包括起点和终点),满足起点到休息站和休息站到终点的路径也是阴阳平衡的。他想知道他一共可以选择多
少种不同的路径。

Input

第1行包含一个整数N。
接下来N-1行,每行包含三个整数a_i、b_i和t_i,表示这条路上药材的类型。

Output

输出符合采药人要求的路径数目。

Sample Input

7
1 2 0
3 1 1
2 4 0
5 2 0
6 3 1
5 7 1

Sample Output

1

HINT

对于100%的数据,N ≤ 100,000。

Source

[Submit][Status][Discuss]

时间: 2024-10-28 23:44:18

【BZOJ】【3697】采药人的路径 & 【3127】【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的特殊情况则

3697. 采药人的路径【点分治】

Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的. 采药人每天都要进行采药活动.他选择的路径是很有讲究的,他认为阴阳平衡是很重要的,所以他走的一定是两种药材数目相等的路径.采药工作是很辛苦的,所以他希望他选出的路径中有一个可以作为休息站的节点(不包括起点和终点),满足起点到休息站和休息站到终点的路径也是阴阳平衡的.他想知道他一共可以选择多少种不同的路径. Input 第1

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> #

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

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

【BZOJ3697】采药人的路径 点分治

[BZOJ3697]采药人的路径 Description 采药人的药田是一个树状结构,每条路径上都种植着同种药材.采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的.采药人每天都要进行采药活动.他选择的路径是很有讲究的,他认为阴阳平衡是很重要的,所以他走的一定是两种药材数目相等的路径.采药工作是很辛苦的,所以他希望他选出的路径中有一个可以作为休息站的节点(不包括起点和终点),满足起点到休息站和休息站到终点的路径也是阴阳平衡的.他想知道他一共可以选择多少种

P4930「FJ2014集训」采药人的路径

题目:P4930「FJ2014集训」采药人的路径 思路: 这篇不算题解,是让自己复习的,什么都没说清楚. 很久没有写点分治了,以前为了赶课件学的太急,板子都没打对就照着题解写题,导致学得很不扎实. 这道题差不多是在郭老师的指导下一点点凑出来的,还是没能自己完整写出一道题,惭愧. 这道题大意是:给出一棵边权为0/1的树,求满足以下条件的路径总数:0的个数等于1的个数,且路径上存在一点到路径两端也满足该条件. 这种求路径总数的题,可以想到用点分治. 把0看作-1,就可以转化为路径边权和为0. 如果没

【BZOJ 3697】采药人的路径

题目链接: TP 题解: 调了好久233. 大概想一想就是树分,然后考虑这样路径(u,v)的特征,以根节点(root)切开,u到root的阴阳差值,和v到root巧合互为相反数,然后考虑要有一个点可作为休息点,即u/v到root的路径中要有一点x与u/v到root的阴阳差值相同,然后维护一下就好. 注意的是阴阳差为0的特判……写挂了调好久,对拍也不好写,真是恶心. 代码: 1 #define Troy 11/23 2 #define inf 0x7fffffff 3 4 #include <bi

bzoj 3697

终于自己独立A了一道点分治. 点分治的题目和树规的题目很像,都是在树上乱搞,但点分治一般和路径更相关,如果用树规做会感觉冗余状态太多,内存和时间都无法承受,如果不用动态规划,直接在原树上运用这道题的方法,又无法保证时间复杂度(点分治让我们的算法对原树的形态依赖更小,可以保证时间复杂度). 1 /************************************************************** 2 Problem: 3697 3 User: idy002 4 Langua

BZOJ3697 采药人的路径 【点分治】

题目 采药人的药田是一个树状结构,每条路径上都种植着同种药材. 采药人以自己对药材独到的见解,对每种药材进行了分类.大致分为两类,一种是阴性的,一种是阳性的. 采药人每天都要进行采药活动.他选择的路径是很有讲究的,他认为阴阳平衡是很重要的,所以他走的一定是两种药材数目相等的路径.采药工作是很辛苦的,所以他希望他选出的路径中有一个可以作为休息站的节点(不包括起点和终点),满足起点到休息站和休息站到终点的路径也是阴阳平衡的.他想知道他一共可以选择多少种不同的路径. 输入格式 第1行包含一个整数N.