题意

一颗树,有边权,和颜色(红或黑)
求,所有的路径中,满足两种颜色的个数差不超过少的颜色的两倍的路径的权值的乘积
路径的权值为经过的边的权值的乘积

题解

边分治牛逼!!!

出现了两个错误,一个是,快速幂时,指数不能先取模,不知道为啥脑子抽筋了…
第二个是,算法有一部分考虑的还不完备,测数据时才发现了漏洞

回到这道题来
求不合法的路径个数
我更喜欢边分治,因为考虑的简单,只会分成两个子问题,不需要考虑容斥等
假设路径的一端预处理出的路径的颜色个数为(a1,b1)(a_1,b_1)(a1​,b1​),在另一端枚举到的路径为(a2,b2)(a_2,b_2)(a2​,b2​)
不满足的情况是
2∗(a1+a2)<b1+b22*(a_1+a_2)<b_1+b_22∗(a1​+a2​)<b1​+b2​ 和 2∗(b1+b2)<a1+a22*(b_1+b_2)<a_1+a_22∗(b1​+b2​)<a1​+a2​ 移项得
2∗a1−b1<b2−2∗a22*a_1-b_1<b_2-2*a_22∗a1​−b1​<b2​−2∗a2​ 和 2∗b1−a1<a2−2∗b22*b_1-a_1<a_2-2*b_22∗b1​−a1​<a2​−2∗b2​
所以,预处理时存下 2∗a1−b12*a_1-b_12∗a1​−b1​ 和 2∗b1−a12*b_1-a_12∗b1​−a1​
求解时,需要的就是一个前缀积
但需要注意的一点:我们还要得出个数,就是预处理出的满足条件的路径个数,因为,假设当前路径的权值为 ccc, 路径个数为 ttt , 答案为 ct∗前缀积c^t*前缀积ct∗前缀积,一开始就是这点忽略了

具体求解时,不需要树状数组,不需要CDQ分治,因为两侧互不影响,直接排序后,二分查找就可以了

这很可能是目前时间 rank1rank1rank1 的原因吧

最后,边分治牛逼

代码

#include<bits/stdc++.h>
#define N 200010
#define INF 0x3f3f3f3f
#define eps 1e-5
#define pi 3.141592653589793
#define mod 998244353
#define P 1000000007
#define LL long long
#define pb push_back
#define fi first
#define se second
#define cl clear
#define si size
#define lb lower_bound
#define ub upper_bound
#define bug(x) cerr<<#x<<"      :   "<<x<<endl
#define mem(x,y) memset(x,0,sizeof(int)*(y+3))
#define sc(x) scanf("%d",&x)
#define scc(x,y) scanf("%d%d",&x,&y)
#define sccc(x,y,z) scanf("%d%d%d",&x,&y,&z)
using namespace std;
typedef  pair<int,int> pp;LL ans,res;
int n,tn,sn,cnt,ct,mn,sz[N],la[N],del[N];
struct node{int from,to,w,t,nxt; }G[N<<1];
struct cc{int x,y,z; };
struct BIT{struct tt{int x,y;bool operator < (const tt z) const{ return x<z.x; }}q[N];int ls[N],cnt;void cls(){cnt=0;}void pre(){sort(q,q+cnt); for(int i=0;i<cnt;i++) {ls[i]=q[i].x; if (i) q[i].y=1ll*q[i-1].y*q[i].y%P; } }int get(int x){return lb(ls,ls+cnt,x)-ls; }void ins(int x,int y){q[cnt++]=tt{x,y}; }
}T1,T2;
inline void add(int x,int y,int w,int t){G[++cnt]=node{x,y,w,t,la[x]}; la[x]=cnt; }
vector<cc> a[N];void rebuild(int x,int fa){int pre=0;for(auto i:a[x]){int v=i.x,w=i.y,t=i.z;if (v==fa) continue;if (!pre){add(x,v,w,t),add(v,x,w,t); pre=x;}else{int k=++tn;add(k,v,w,t), add(v,k,w,t);add(k,pre,1,2), add(pre,k,1,2);pre=k;}rebuild(v,x);}
}void findct(int x,int fa){sz[x]=1;for(int i=la[x];i;i=G[i].nxt){int v=G[i].to;if (del[i>>1]||v==fa) continue;findct(v,x);sz[x]+=sz[v];int tmp=max(sz[v],sn-sz[v]);if (tmp<mn){ct=i;mn=tmp;}}
}void gao(int x,int fa,int a,int b,LL c){if (x<=n) T1.ins(2*a-b,c),T2.ins(2*b-a,c);for(int i=la[x];i;i=G[i].nxt)if (!del[i>>1]&&G[i].to!=fa)gao(G[i].to,x,a+(G[i].t==0),b+(G[i].t==1),c*G[i].w%P);
}LL qpow(LL a,LL b){LL res=1; while(b){if (b&1) res=res*a%P; a=a*a%P; b>>=1; } return res; }
void get(int x,int fa,int a,int b,LL c){if (x<=n) {int t=T1.get(b-2*a);res=res*qpow(c,t)%P*(t?T1.q[t-1].y:1)%P;t=T2.get(a-2*b);res=res*qpow(c,t)%P*(t?T2.q[t-1].y:1)%P;}for(int i=la[x];i;i=G[i].nxt)if (!del[i>>1]&&G[i].to!=fa)get(G[i].to,x,a+(G[i].t==0),b+(G[i].t==1),c*G[i].w%P);
}void dfs(int x){int u=G[x].from,v=G[x].to;if (sz[u]<sz[v]) swap(u,v);del[x>>1]=1;T1.cls(); T2.cls();gao(u,-1,0,0,1);T1.pre(); T2.pre();get(v,-1,G[x].t==0,G[x].t==1,G[x].w);int tot=sn;sn=tot-sz[v]; mn=INF;findct(u,-1);if (mn!=INF)dfs(ct);sn=sz[v]; mn=INF;findct(v,-1);if (mn!=INF)dfs(ct);
}void pre(int x,int fa){sz[x]=1;for(auto i:a[x])if (i.x!=fa){pre(i.x,x);sz[x]+=sz[i.x];ans=ans*qpow(i.y,1ll*(n-sz[i.x])*sz[i.x])%P;}
}int main(int argc, char const *argv[]){sc(n);for(int i=1;i<n;i++){int x,y,z,w;scc(x,y); scc(z,w);a[x].pb(cc{y,z,w});a[y].pb(cc{x,z,w});}ans=res=cnt=1;pre(1,-1);tn=n;      rebuild(1,-1);sn=tn; mn=INF;findct(1,-1);dfs(ct);printf("%lld\n",ans*qpow(res,P-2)%P);return 0;
}

Codeforces 833D Red-Black Cobweb 边分治相关推荐

  1. Codeforces 833D Red-Black Cobweb [点分治]

    洛谷 Codeforces 思路 看到树上路径的统计,容易想到点分治. 虽然只有一个限制,但这个限制比较麻烦,我们把它拆成两个. 设黑边有\(a\)条,白边有\(b\)条,那么有 \[ 2a\geq ...

  2. Codeforces 997D Cycles in Product (点分治、DP计数)

    题目链接 https://codeforces.com/contest/997/problem/D 题解 点分治这个思路想不到== 首先这两棵树的笛卡尔积并没有什么用处,因为笛卡尔积中的环就是两棵树中 ...

  3. Educational Codeforces Round 32 G. Xor-MST 01tire + 分治 + Boruvka

    传送门 文章目录 题意: 思路: 题意: 给你一个长度为nnn序列aaa,每两个点之间的边权为ai⊕aja_i\oplus a_jai​⊕aj​,问你最小生成树的权值是多少. n≤2e5,ai< ...

  4. CodeForces - 1324D Pair of Topics (分治+排序)

    CodeForces - 1324D Pair of Topics 题目大意: 这题大意ai+aj>bi+bj全在这个式子上,就问你满足的组合有几种, 题目分析: 整理一下,得到(ai-bi)+ ...

  5. codeforces 549F Yura and Developers(分治、启发式合并)

    codeforces 549F Yura and Developers 题意 给定一个数组,问有多少区间满足:去掉最大值之后,和是k的倍数. 题解 分治,对于一个区间,找出最大值之后,分成两个区间. ...

  6. CF833D Red-Black Cobweb 点分治、树状数组

    传送门 统计所有路径的边权乘积的乘积,不难想到点分治求解. 边权颜色比例在\([\frac{1}{2},2]\)之间,等价于\(2B \geq R , 2R \geq B\)(\(R,B\)表示红色和 ...

  7. 清北学堂培训2019.4.28

    Day 1(冯哲) 今天的内容很杂但却都是基础知识 主要分为下面几个点 枚举 枚举也称作穷举,指的是从问题所有可能的解的集合中一一枚举各元素.用题目中给定的检验条件判定哪些是无用的,哪些是有用的.能使 ...

  8. codeforces 293E Close Vertices 点分治+滑窗+treap

    http://codeforces.com/contest/293/problem/E 题意:求树上合法点对的个数.合法条件为:路径长度<=W,路径边数<=L. 显然是点分治.求解的时候第 ...

  9. Codeforces 448C Painting Fence:分治

    题目链接:http://codeforces.com/problemset/problem/448/C 题意: 有n个木板竖着插成一排栅栏,第i块木板高度为a[i]. 你现在要将栅栏上所有地方刷上油漆 ...

最新文章

  1. C# BeginInvoke与EndInvoke的使用
  2. 在 Linux 下使用 水星MW150cus (RTL8188CUS芯片)无线网卡
  3. 2018 大湾区(深圳) .NET技术分享交流会 第一期
  4. python接口自动化(二十五)--unittest断言——下(详解)
  5. C++ vector用法
  6. 北方人思想为什么落后_广西人为什么很少到北方打工?
  7. HDU 1048 The Hardest Problem Ever
  8. GoldenGate碎碎念
  9. pure-ftpd 配置
  10. 程序员的五种不同寻常的特质
  11. 怎么在GIF动态图中添加文字
  12. implicit declaration of function —— 函数隐式声明 警告
  13. maven 使用本地库
  14. 计算机蓝屏显示的英文是什么,电脑蓝屏出现一堆英文怎么解决?
  15. HTTP Error 503错误
  16. 应用程序崩溃定位查找 (二)
  17. 车载网络: 常见车载网络
  18. 免费换背景app、在线修改图片像素、在线照片压缩网站
  19. VuePress学习笔记
  20. 逍遥模拟器调试模式设置

热门文章

  1. 如何把Pod本地化(Localize)
  2. Q-M法(列表法)化简 C++ 实现
  3. 更换一个已到使用寿命的墨盒--Epson
  4. 物理信息融合系统CPS---数据流(SDF/DDF)
  5. 一行代码获取股票、基金数据,并绘制K线图
  6. 简单说说 RPC 框架,你 悟到了吗?
  7. 单细胞转录组实战01: CellRanger7定量
  8. mac安装golang,编写第一个go程序
  9. 测试人的Java之编程那点事
  10. 两例司法实践撕开了一个口子,区块链应用落地会加速吗?