[CODECHEF]TREECNT2
题意:一棵带边权的树,边权可单边修改,问初始时和每次修改后有多少条路径$\gcd=1$
首先考虑用反演求答案,设$f(n)$为路径$\gcd=n$的路径条数,$g(n)$为路径$\gcd$是$n$倍数的路径条数,那么$g(n)=\sum\limits_{n|d}f(d)$,所以$f(n)=\sum\limits_{d|n}\mu\left(\frac dn\right)g(d)$,答案就是$f(1)=\sum\limits_{d}\mu(d)g(d)$
我们现在要求$g(d)$,先考虑没有修改怎么做,我们对每个$d$预处理出是$d$倍数的那些边(这里可以直接枚举边权的约数,因为边权$\leq10^6$)用这些边构图,答案就是每个连通块的$\binom{siz}2$之和,这里可以用并查集做
加上修改就只预处理那些不被修改的边,先用这些不被修改的边建并查集,每次对第$i$个询问,修改第$1\cdots i$条边的边权后再把这至多$q$条边插进并查集中,再统计答案
总时间复杂度貌似是$O(wq^2\log n)$???但是加一些小优化好像可以过...
#include<stdio.h> #include<vector> using namespace std; typedef long long ll; const int T=1000000; int pr[T+10],mu[T+10]; bool np[T+10]; void sieve(){ int i,j,M=0; mu[1]=1; for(i=2;i<=T;i++){ if(!np[i]){ pr[++M]=i; mu[i]=-1; } for(j=1;j<=M&&i*pr[j]<=T;j++){ np[i*pr[j]]=1; if(i%pr[j]==0)break; mu[i*pr[j]]=-mu[i]; } } } struct edge{ int x,y,w; }E[100010]; struct ask{ int i,v; }Q[110]; bool del[100010],us[T+10]; vector<int>G[T+10]; ll C; int fa[100010],dep[100010],siz[100010],M; struct oper{ int u,f,d,s; oper(int _u=0,int _f=0,int _d=0,int _s=0){u=_u;f=_f;d=_d;s=_s;} }stk[200010]; void add(int u){ stk[++M]=oper(u,fa[u],dep[u],siz[u]); } int get(int x){ while(x!=fa[x])x=fa[x]; return x; } void merge(int x,int y){ x=get(x); y=get(y); if(x==y)return; if(dep[x]<dep[y])swap(x,y); add(x); add(y); fa[y]=x; if(dep[x]==dep[y])dep[x]++; C+=(ll)siz[x]*siz[y]; siz[x]+=siz[y]; } void roll(){ int u=stk[M].u; fa[u]=stk[M].f; dep[u]=stk[M].d; siz[u]=stk[M].s; M--; } ll ans[110]; int val[100010]; int main(){ int n,q,i,j,k,tM; ll tC; sieve(); scanf("%d",&n); for(i=1;i<n;i++)scanf("%d%d%d",&E[i].x,&E[i].y,&E[i].w); scanf("%d",&q); for(i=1;i<=q;i++){ scanf("%d%d",&Q[i].i,&Q[i].v); del[Q[i].i]=1; } for(i=1;i<n;i++){ if(!del[i]){ for(j=1;j*j<=E[i].w;j++){ if(E[i].w%j==0){ G[j].push_back(i); if(j*j!=E[i].w)G[E[i].w/j].push_back(i); } } }else{ for(j=1;j*j<=E[i].w;j++){ if(E[i].w%j==0)us[j]=us[E[i].w/j]=1; } } } for(i=1;i<=q;i++){ for(j=1;j*j<=Q[i].v;j++){ if(Q[i].v%j==0)us[j]=us[Q[i].v/j]=1; } } for(i=1;i<=n;i++){ fa[i]=i; dep[i]=1; siz[i]=1; } for(i=1;i<=T;i++){ if(mu[i]&&!(G[i].empty()&&!us[i])){ C=0; M=0; for(int j:G[i])merge(E[j].x,E[j].y); tM=M; tC=C; for(j=1;j<=q;j++)val[Q[j].i]=E[Q[j].i].w; for(j=0;j<=q;j++){ val[Q[j].i]=Q[j].v; C=tC; if(us[i]){ for(k=1;k<=q;k++){ if(val[Q[k].i]%i==0)merge(E[Q[k].i].x,E[Q[k].i].y); } } ans[j]+=mu[i]*C; while(M>tM)roll(); } while(M)roll(); } } for(i=0;i<=q;i++)printf("%lld\n",ans[i]); }
[CODECHEF]TREECNT2的更多相关文章
- 【BZOJ-3514】Codechef MARCH14 GERALD07加强版 LinkCutTree + 主席树
3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1288 Solved: 490 ...
- 【BZOJ4260】 Codechef REBXOR 可持久化Trie
看到异或就去想前缀和(⊙o⊙) 这个就是正反做一遍最大异或和更新答案 最大异或就是很经典的可持久化Trie,从高到低贪心 WA: val&(1<<(base-1))得到的并不直接是 ...
- codechef 两题
前面做了这场比赛,感觉题目不错,放上来. A题目:对于数组A[],求A[U]&A[V]的最大值,因为数据弱,很多人直接排序再俩俩比较就过了. 其实这道题类似百度之星资格赛第三题XOR SUM, ...
- codechef January Challenge 2014 Sereja and Graph
题目链接:http://www.codechef.com/JAN14/problems/SEAGRP [题意] 给n个点,m条边的无向图,判断是否有一种删边方案使得每个点的度恰好为1. [分析] 从结 ...
- BZOJ3509: [CodeChef] COUNTARI
3509: [CodeChef] COUNTARI Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 339 Solved: 85[Submit][St ...
- CodeChef CBAL
题面: https://www.codechef.com/problems/CBAL 题解: 可以发现,我们关心的仅仅是每个字符出现次数的奇偶性,而且字符集大小仅有 26, 所以我们状态压缩,记 a[ ...
- CodeChef FNCS
题面:https://www.codechef.com/problems/FNCS 题解: 我们考虑对 n 个函数进行分块,设块的大小为S. 每个块内我们维护当前其所有函数值的和,以及数组中每个元素对 ...
- codechef Prime Distance On Tree(树分治+FFT)
题目链接:http://www.codechef.com/problems/PRIMEDST/ 题意:给出一棵树,边长度都是1.每次任意取出两个点(u,v),他们之间的长度为素数的概率为多大? 树分治 ...
- BZOJ 3221: [Codechef FEB13] Obserbing the tree树上询问( 可持久化线段树 + 树链剖分 )
树链剖分+可持久化线段树....这个一眼可以看出来, 因为可持久化所以写了标记永久化(否则就是区间修改的线段树的持久化..不会), 结果就写挂了, T得飞起...和管理员拿数据调后才发现= = 做法: ...
随机推荐
- MSSQL DBcheck
--1.创建数据库. --create database MyDatabase; --删除数据库 --drop database MyDatabase; ----------------------- ...
- js_开发小技巧记录(一)
(一) 生成从minNum到maxNum的随机数 <!DOCTYPE html> <html> <head> <meta charset="UTF- ...
- delphi按钮文字换行
delphi按钮有TButton和TBitButton,而TButton不支持换行,TBitButton支持 拖拽TBitButton按钮以后,按alt+F12进入找到TBitButton的capti ...
- js中的for in 循环
1.数组 使用for in 遍历数组时,其索引被视为对象的属性,从而直接输出数组的索引 var arr = ["a","b","c"]; f ...
- ubuntu gnome桌面秀
之前装的是ubuntu14.10gnome版的 然后一路升级成15.04,到今天的15.10 最后发现现在的gnome桌面已经非常适合我的工作了 先放一张图,这是我的桌面 原来使用ubuntu15.0 ...
- 2017-2018-1 《Linux内核原理与设计》第十二周作业
<linux内核原理与设计>第十二周作业 Sql注入基础原理介绍 分组: 和20179215袁琳完成实验 一.实验说明 SQL注入攻击通过构建特殊的输入作为参数传入Web应用程序,而这 ...
- mysql中的enum型
enum设置后 值只能是给出的值中的其中一个 mysql> create table enum(e enum('1','2','3','4','5','6','7','8','9','10')) ...
- shell下在while循环中使用ssh命令的问题
1 现象描述 最近使用ssh批量执行命令(已经做了密钥互信了),脚本读取配置文件中的主机列表(内容为每行一台主机IP地址),然后执行,可是每次只是执行第一台,就退出循环了. 2 排查思路 由于脚本比较 ...
- JS面试题第一弹
1.javascript的typeof返回哪些数据类型 alert(typeof [1, 2]); //object alert(typeof 'leipeng'); //string ...
- jquery文档加载几种写法,图片加载写法
jquery文档加载写法: $(function(){ }) ; //个人最常使用方式 $(document).ready(function(){ }); //调用文档对象下的ready方法传入一个函 ...