Codeforces 833D Red-Black Cobweb 边分治
题意
一颗树,有边权,和颜色(红或黑)
求,所有的路径中,满足两种颜色的个数差不超过少的颜色的两倍的路径的权值的乘积
路径的权值为经过的边的权值的乘积
题解
边分治牛逼!!!
出现了两个错误,一个是,快速幂时,指数不能先取模,不知道为啥脑子抽筋了…
第二个是,算法有一部分考虑的还不完备,测数据时才发现了漏洞
回到这道题来
求不合法的路径个数
我更喜欢边分治,因为考虑的简单,只会分成两个子问题,不需要考虑容斥等
假设路径的一端预处理出的路径的颜色个数为(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 边分治相关推荐
- Codeforces 833D Red-Black Cobweb [点分治]
洛谷 Codeforces 思路 看到树上路径的统计,容易想到点分治. 虽然只有一个限制,但这个限制比较麻烦,我们把它拆成两个. 设黑边有\(a\)条,白边有\(b\)条,那么有 \[ 2a\geq ...
- Codeforces 997D Cycles in Product (点分治、DP计数)
题目链接 https://codeforces.com/contest/997/problem/D 题解 点分治这个思路想不到== 首先这两棵树的笛卡尔积并没有什么用处,因为笛卡尔积中的环就是两棵树中 ...
- Educational Codeforces Round 32 G. Xor-MST 01tire + 分治 + Boruvka
传送门 文章目录 题意: 思路: 题意: 给你一个长度为nnn序列aaa,每两个点之间的边权为ai⊕aja_i\oplus a_jai⊕aj,问你最小生成树的权值是多少. n≤2e5,ai< ...
- CodeForces - 1324D Pair of Topics (分治+排序)
CodeForces - 1324D Pair of Topics 题目大意: 这题大意ai+aj>bi+bj全在这个式子上,就问你满足的组合有几种, 题目分析: 整理一下,得到(ai-bi)+ ...
- codeforces 549F Yura and Developers(分治、启发式合并)
codeforces 549F Yura and Developers 题意 给定一个数组,问有多少区间满足:去掉最大值之后,和是k的倍数. 题解 分治,对于一个区间,找出最大值之后,分成两个区间. ...
- CF833D Red-Black Cobweb 点分治、树状数组
传送门 统计所有路径的边权乘积的乘积,不难想到点分治求解. 边权颜色比例在\([\frac{1}{2},2]\)之间,等价于\(2B \geq R , 2R \geq B\)(\(R,B\)表示红色和 ...
- 清北学堂培训2019.4.28
Day 1(冯哲) 今天的内容很杂但却都是基础知识 主要分为下面几个点 枚举 枚举也称作穷举,指的是从问题所有可能的解的集合中一一枚举各元素.用题目中给定的检验条件判定哪些是无用的,哪些是有用的.能使 ...
- codeforces 293E Close Vertices 点分治+滑窗+treap
http://codeforces.com/contest/293/problem/E 题意:求树上合法点对的个数.合法条件为:路径长度<=W,路径边数<=L. 显然是点分治.求解的时候第 ...
- Codeforces 448C Painting Fence:分治
题目链接:http://codeforces.com/problemset/problem/448/C 题意: 有n个木板竖着插成一排栅栏,第i块木板高度为a[i]. 你现在要将栅栏上所有地方刷上油漆 ...
最新文章
- C# BeginInvoke与EndInvoke的使用
- 在 Linux 下使用 水星MW150cus (RTL8188CUS芯片)无线网卡
- 2018 大湾区(深圳) .NET技术分享交流会 第一期
- python接口自动化(二十五)--unittest断言——下(详解)
- C++ vector用法
- 北方人思想为什么落后_广西人为什么很少到北方打工?
- HDU 1048 The Hardest Problem Ever
- GoldenGate碎碎念
- pure-ftpd 配置
- 程序员的五种不同寻常的特质
- 怎么在GIF动态图中添加文字
- implicit declaration of function —— 函数隐式声明 警告
- maven 使用本地库
- 计算机蓝屏显示的英文是什么,电脑蓝屏出现一堆英文怎么解决?
- HTTP Error 503错误
- 应用程序崩溃定位查找 (二)
- 车载网络: 常见车载网络
- 免费换背景app、在线修改图片像素、在线照片压缩网站
- VuePress学习笔记
- 逍遥模拟器调试模式设置