【CF833D】Red-Black Cobweb(点分治)

题面

CF

有一棵树,每条边有一个颜色(黑白)和一个权值,定义一条路径是好的,当且仅当这条路径上所有边的黑白颜色个数a,b满足2min(a,b)>=max(a,b),一条路径的权值为路径上所有边的权值的乘积,求所有好的路径的权值乘积.

\(n<=10^5\)

题解

首先看到求所有路径相关的内容,不难想到点分治。

两个限制可以转化为需要同时满足:\(2a\ge b,2b\ge a\)。

对于两条路径\(a1,b1/a2,b2\)考虑如何合并。

需要满足的两个条件就变成了\(2(a1+a2)\ge b1+b2\)以及\(2(b1+b2)\ge a1+a2\)

再稍微拆开看看就变成了\(2a1-b1\ge b2-2a2\),另一个类似。

这里怎么计算总的方案数,那么就用总数减去不合法的,如果不合法显然只会有一个不等式不合法(因为另外一个不等式是由最大值的两倍大于较小值得到的,它无论如何都会是对的),那么只需要统计有一个不合法的所有链就好了。

#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 100100
#define MOD 1000000007
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int fpow(int a,int b){int s=1;while(b){if(b&1)s=1ll*s*a%MOD;a=1ll*a*a%MOD;b>>=1;}return s;}
struct Line{int v,next,w,c;}e[MAX<<1];
int h[MAX],cnt=1;
inline void Add(int u,int v,int w,int c){e[cnt]=(Line){v,h[u],w,c};h[u]=cnt++;}
int Size,mx,rt,size[MAX];bool vis[MAX];
int n,N,ans,ans1=1,ans2=1;
int lb(int x){return x&(-x);}
struct BIT
{
int c1[MAX<<3],c2[MAX<<3];
void pre(){for(int i=1;i<=N;++i)c1[i]=1,c2[i]=0;}
void Modify(int x,int w){while(x<=N)c1[x]=1ll*c1[x]*w%MOD,c2[x]+=1,x+=lb(x);}
void Clear(int x){while(x<=N)c1[x]=1,c2[x]=0,x+=lb(x);}
int Querys(int x){int s=1;while(x)s=1ll*s*c1[x]%MOD,x-=lb(x);return s;}
int Queryt(int x){int s=0;while(x)s+=c2[x],x-=lb(x);return s;}
int Querys(int l,int r){return 1ll*Querys(r)*fpow(Querys(l-1),MOD-2)%MOD;}
int Queryt(int l,int r){return Queryt(r)-Queryt(l-1);}
}c1,c2;
void Getroot(int u,int ff)
{
int ret=0;size[u]=1;
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(v==ff||vis[v])continue;
Getroot(v,u);size[u]+=size[v];ret=max(ret,size[v]);
}
ret=max(ret,Size-size[u]);
if(ret<mx)mx=ret,rt=u;
}
struct Pair{int a,b,w;}S[MAX],T[MAX];
int top,sum,W,SW,py;
void dfs(int u,int ff,int a,int b,int w)
{
T[++top]=(Pair){a,b,w};W=1ll*w*W%MOD;
for(int i=h[u];i;i=e[i].next)
if(e[i].v!=ff&&!vis[e[i].v])
dfs(e[i].v,u,a+(e[i].c^1),b+e[i].c,1ll*w*e[i].w%MOD);
}
void Divide(int u)
{
vis[u]=true;sum=0;SW=1;S[++sum]=(Pair){0,0,1};
c1.Modify(py,1);c2.Modify(py,1);
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(vis[v])continue;
top=0;W=1;dfs(e[i].v,u,e[i].c^1,e[i].c,e[i].w);
ans1=1ll*ans1*fpow(W,sum)%MOD*fpow(SW,top)%MOD;
SW=1ll*SW*W%MOD;
for(int j=1;j<=top;++j)
{
int A=T[j].b-2*T[j].a-1+py,B=T[j].a-2*T[j].b-1+py;
ans2=1ll*ans2*c1.Querys(2,A)%MOD*fpow(T[j].w,c1.Queryt(2,A))%MOD;
ans2=1ll*ans2*c2.Querys(2,B)%MOD*fpow(T[j].w,c2.Queryt(2,B))%MOD;
}
for(int j=1;j<=top;++j)
{
int A=2*T[j].a-T[j].b+py;c1.Modify(A,T[j].w);
int B=2*T[j].b-T[j].a+py;c2.Modify(B,T[j].w);
S[++sum]=T[j];
}
}
for(int j=1;j<=sum;++j)
{
int A=2*S[j].a-S[j].b+py;c1.Clear(A);
int B=2*S[j].b-S[j].a+py;c2.Clear(B);
}
for(int i=h[u];i;i=e[i].next)
{
int v=e[i].v;if(vis[v])continue;
Size=mx=size[v];Getroot(v,u);
Divide(rt);
}
}
int main()
{
n=read();py=n+n+2;N=5*n;c1.pre();c2.pre();
for(int i=1,u,v,w,c;i<n;++i)
u=read(),v=read(),w=read(),c=read(),Add(u,v,w,c),Add(v,u,w,c);
Size=mx=n;Getroot(1,0);Divide(rt);
ans=1ll*ans1*fpow(ans2,MOD-2)%MOD;
printf("%d\n",ans);
return 0;
}

【CF833D】Red-Black Cobweb(点分治)的更多相关文章

  1. 【CF833D】Red-Black Cobweb

    [CF833D]Red-Black Cobweb 题面 洛谷 题解 看到这种统计路径的题目当然是淀粉质啦. 考虑转化一下信息设一条路径上有红点\(a\)个,黑点\(b\)个 则\(2min(a,b)\ ...

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

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

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

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

  4. Codeforces 833D Red-black Cobweb【树分治】

    D. Red-black Cobweb time limit per test:6 seconds memory limit per test:256 megabytes input:standard ...

  5. CF833D Red-Black Cobweb

    题面 题解 点分治大火题... 设白边数量为$a$,黑边为$b$,则$2min(a,b)\geq max(a,b)$ 即$2a\geq b\;\&\&2b\geq a$ 考虑点分治时如 ...

  6. 题解 CF833D Red-Black Cobweb

    题目传送门 题目大意 给出一个 \(n\) 个点的树,每条边有边权和颜色 \(0,1\) ,定义一条链合法当且仅当 \(0,1\) 颜色的边数之比小于等于 \(2\) ,求所有合法的链的边权之积的积. ...

  7. 【CDQ分治】[HNOI2010]城市建设

    题目链接 线段树分治+LCT只有80 然后就有了CDQ分治的做法 把不可能在生成树里的扔到后面 把一定在生成树里的扔到并查集里存起来 分治到l=r,修改边权,跑个kruskal就行了 由于要支持撤销, ...

  8. URAL 1181 Cutting a Painted Polygon【递归+分治】

    题目: http://acm.timus.ru/problem.aspx?space=1&num=1181 http://acm.hust.edu.cn/vjudge/contest/view ...

  9. POJ 2114 点分治

    思路: 点分治 //By SiriusRen #include <cstdio> #include <cstring> #include <algorithm> u ...

随机推荐

  1. .net之httphandler小记

    本地调试代码遇到的一个问题,没有走URL路由器(UrlReWriter : IHttpHandlerFactory),于是网上科普了一下原理,主要有两点: 1.asp.net在处理http请求时,会由 ...

  2. Redis服务端的搭建(初级)

    前方低能,仅适合入门级菜鸟阅读,大神大牛通通闪开! 前言:redis经常被用来做缓存(原因自行科普),基于学习的需要自己搭建了一个redis服务器,考虑到项目的分布式部署,所以前期开始的时候,redi ...

  3. PlainElastic.Net

    PlainElastic.Net PlainElastic.Net The really plain Elastic Search .Net client. Idea Installation How ...

  4. 【转】Restful是什么

    REST的概念是什么 维基百科  表现层状态转换(REST,英文:Representational State Transfer)是Roy Thomas Fielding博士于2000年在他的博士论文 ...

  5. VS2008引入头文件包含目录和lib库目录

    全局级别的引入 为VS所有项目设置包含目录和库目录,对所有项目都有效 如下图所示:工具-选项-项目和解决方案-VC++目录-包含文件:在此添加头文件目录即可 工具-选项-项目和解决方案-VC++目录- ...

  6. 从零开始搭建VUE项目

    前言: 此样板面向大型,严肃的项目,并假定您对Webpack和vue-loader有些熟悉. 请务必阅读vue-loader的常见工作流配方的文档. 如果您只想尝试vue-loader或者鞭打一个快速 ...

  7. MT4用EA测试历史数据时日志出现:stopped because of stop out

    今天用嘉盛的MT4测试一个EA,谁知道才走了十几天数据就完 了,看结果本金也没亏完啊,才亏了一半,而且我测的是1年的时间. 查看日志一有条警告:stopped because of stop out, ...

  8. NOIP2015提高组复赛B 子串

    题目链接:https://ac.nowcoder.com/acm/contest/263/B 题目大意: 略 分析: 设preA(i)为字符串A中第1个字符到第i个字符构成的字符串. 设preB(i) ...

  9. git基本操作1

    1.创建版本库 在文件夹下,打开Git Bash Here ,然后执行git init,文件夹中会多出.git文件夹.(.git可能是隐藏的) 2.创建a.txt vim  a.txt ,并添加到版本 ...

  10. RocketMQ消息队列安装

    一.官方安装文档 http://rocketmq.apache.org/docs/quick-start/ 下载地址 https://github.com/apache/rocketmq/releas ...