LINK:小V和gcd树

时限是8s 所以当时好多nq的暴力都能跑过.

考虑每次询问暴力 跳父亲 这样是nq的 4e8左右 随便过。

不过每次跳到某个点的时候需要得到边权 如果直接暴力gcd的话 nqlogn就过不了了。

这里有两种解决办法:

一种是比赛的时候队友想的 一种是比较容易想到的方法。

前者套用树链剖分 只对重儿子的边进行修改 这样每次修改的复杂度为qlog.

考虑查询的时候沿着重链向上跳 这样重边可以O(1)得到答案 轻边暴力。

那么就得到了一个 nq+qlog^2的做法了。

当然可以进行根号分治 对于度数>sqrt的点不管 对于度数<sqrt的暴力修改。

前者在暴力跳的时候暴力查询 这样前者最多遇到sqrt(n)个这样的点 后者也是要修改sqrt次。

所以总复杂度为 nq+qsqrt(n)log.

两种暴力都是基于nq的暴力的。

题解给了一个树上带修莫队的做法 不过不是很优秀复杂度接近nq的暴力 而且写起来估计也比较难写..

对于这类问题还是考虑主席树 修改带上树状数组。

不过这个修改是多个点的点权修改 考虑树链剖分。

只修改重边上的信息 轻边暴力 那么利用主席树套树状数组 就可以了。

一个比较naive的想法是 只对重链开树状数组 这样是不对的。

考虑每次查询 是笔直的链查询 所以我们直接利用树状数组维护dfs序即可解决这个问题。

总复杂度 qlog^3+qlog^2.这个做法还算是比较优美的。

const int MAXN=20010;
int n,Q,maxx,len,cnt,id,top1,top2;
int f[MAXN],d[MAXN],a[MAXN],w[MAXN],son[MAXN],dfn[MAXN],sz[MAXN],pos[MAXN];
int lin[MAXN],ver[MAXN<<1],nex[MAXN<<1],root[MAXN],ql[MAXN],qr[MAXN],top[MAXN];
inline int gcd(int a,int b){return b?gcd(b,a%b):a;}
inline void add(int x,int y)
{
ver[++len]=y;nex[len]=lin[x];lin[x]=len;
ver[++len]=x;nex[len]=lin[y];lin[y]=len;
}
struct wy
{
int l,r;
int sum;
}t[MAXN*900];
inline void dfs(int x,int fa)
{
d[x]=d[fa]+1;f[x]=fa;sz[x]=1;
go(x)if(tn!=fa)
{
dfs(tn,x);
sz[x]+=sz[tn];
if(sz[tn]>sz[son[x]])son[x]=tn;
}
}
inline void dp(int x,int fa)
{
top[x]=fa;dfn[x]=++cnt;pos[cnt]=x;
if(!son[x])return;
dp(son[x],fa);
go(x)if(tn!=f[x]&&tn!=son[x])dp(tn,tn);
}
inline void insert(int &p,int l,int r,int x,int y)
{
if(!p)p=++id;sum(p)+=y;
if(l==r)return;
int mid=(l+r)>>1;
if(x<=mid)insert(l(p),l,mid,x,y);
else insert(r(p),mid+1,r,x,y);
}
inline void insert(int x,int v,int y)
{
while(x<=n)
{
insert(root[x],1,maxx,v,y);
x+=x&(-x);
}
}
inline void modify(int x,int v)
{
if(son[x])
{
insert(dfn[son[x]],w[son[x]],-1);
w[son[x]]=gcd(v,a[son[x]]);
insert(dfn[son[x]],w[son[x]],1);
}
if(f[x])
{
insert(dfn[x],w[x],-1);
w[x]=gcd(v,a[f[x]]);
insert(dfn[x],w[x],1);
}
a[x]=v;
}
inline int query(int l,int r,int x)//查<=x的个数.
{
if(l==r)
{
int cnt=0;
rep(1,top1,i)cnt-=sum(ql[i]);
rep(1,top2,i)cnt+=sum(qr[i]);
return cnt;
}
int mid=(l+r)>>1;
if(x>mid)
{
int cnt=0;
rep(1,top1,i)cnt-=sum(l(ql[i]));
rep(1,top2,i)cnt+=sum(l(qr[i]));
rep(1,top1,i)ql[i]=r(ql[i]);
rep(1,top2,i)qr[i]=r(qr[i]);
return cnt+query(mid+1,r,x);
}
rep(1,top1,i)ql[i]=l(ql[i]);
rep(1,top2,i)qr[i]=l(qr[i]);
return query(l,mid,x);
}
inline int ask(int s1,int s2,int k)
{
if(s1==s2)return 0;
top1=top2=0;
while(s1)ql[++top1]=root[s1],s1-=s1&(-s1);
while(s2)qr[++top2]=root[s2],s2-=s2&(-s2);
return query(1,maxx,k);
}
inline int Task(int x,int y,int k)
{
int cnt=0;
int fx=top[x],fy=top[y];
while(fx!=fy)
{
if(d[fx]<d[fy])swap(x,y),swap(fx,fy);
cnt+=ask(dfn[fx],dfn[x],k);
int ww=gcd(a[fx],a[f[fx]]);
cnt+=(ww<=k);
x=f[fx];fx=top[x];
}
if(d[x]<d[y])swap(x,y);
cnt+=ask(dfn[y],dfn[x],k);
return cnt;
}
int main()
{
//freopen("1.in","r",stdin);
get(n);get(Q);maxx=1000000;
rep(1,n,i)get(a[i]);
rep(2,n,i)add(read(),read());
dfs(1,0);dp(1,1);
rep(2,n,i)insert(dfn[i],w[i]=gcd(a[i],a[f[i]]),1);
rep(1,Q,i)
{
int op,x;
get(op);get(x);
if(op==1)modify(x,read());
else
{
int get(v);
put(Task(x,v,read()));
}
}
return 0;
}

5.15 牛客挑战赛40 E 小V和gcd树 树链剖分 主席树 树状数组 根号分治的更多相关文章

  1. 5.15 牛客挑战赛40 C 小V和字符串 数位dp 计数问题

    LINK:小V和字符串 容易想到只有1个数相同的 才能有贡献. 知道两个01串 那么容易得到最小步数 大体上就是 第一个串的最前的1和第二个串最前的1进行匹配. 容易想到设f[i][j]表示 前i位1 ...

  2. 5.15 牛客挑战赛40 B 小V的序列 关于随机均摊分析 二进制

    LINK:小V的序列 考试的时候 没想到正解 于是自闭. 题意很简单 就是 给出一个序列a 每次询问一个x 问序列中是否存在y 使得x^y的二进制位位1的个数<=3. 容易想到 暴力枚举. 第一 ...

  3. 牛客练习赛40 A 小D的剧场 (思维dp)

    链接:https://ac.nowcoder.com/acm/contest/369/A 题目描述 若你摘得小的星星 你将得到小的幸福  若你摘得大的星星 你将得到大的财富  若两者都能摘得 你将得到 ...

  4. 牛客练习赛40 C 小A与欧拉路(树的直径)

    链接:https://ac.nowcoder.com/acm/contest/369/C 题目描述 小A给你了一棵树,对于这棵树上的每一条边,你都可以将它复制任意(可以为0)次(即在这条边连接的两个点 ...

  5. 牛客挑战赛 30 A 小G数数

    题目链接:https://ac.nowcoder.com/acm/contest/375/A 分析:我写的时候竟然把它当成了DP....... 还建了个结构体DP数组,保存一二位,不知道当时脑子在抽啥 ...

  6. 牛客挑战赛40 VMware和基站 set 二分 启发式合并 区间覆盖

    LINK:VMware和基站 一道 做法并不常见的题目 看起来很难写 其实set维护线段就可以解决了. 容易想到 第二个操作借用启发式合并可以得到一个很不错的复杂度 不过利用线段树维护这个东西 在区间 ...

  7. 【牛客挑战赛30D】小A的昆特牌(组合问题抽象到二维平面)

    点此看题面 大致题意: 有\(S\)张无编号的牌,可以将任意张牌锻造成\(n\)种步兵或\(m\)种弩兵中的一种,求最后步兵数量大于等于\(l\)小于等于\(r\)的方案数. 暴力式子 首先我们来考虑 ...

  8. 牛客小白月赛13-J小A的数学题 (莫比乌斯反演)

    链接:https://ac.nowcoder.com/acm/contest/549/J来源:牛客网 题目描述 小A最近开始研究数论题了,这一次他随手写出来一个式子,∑ni=1∑mj=1gcd(i,j ...

  9. 牛客小白月赛13 小A的回文串(Manacher)

    链接:https://ac.nowcoder.com/acm/contest/549/B来源:牛客网 题目描述 小A非常喜欢回文串,当然我们都知道回文串这种情况是非常特殊的.所以小A只想知道给定的一个 ...

随机推荐

  1. 给大家分享一下less的使用几个技巧

    1.层级关系 让这个box范围内的全部包进来,这样的话就完美的进行调节,再也不用到处找第几行第几个,我刚才在哪个位置给覆盖了.一看便知! .box{ width: %; height: 300px; ...

  2. 结合实际需求,在webapi内利用WebSocket建立单向的消息推送平台,让A页面和服务端建立WebSocket连接,让其他页面可以及时给A页面推送消息

    1.需求示意图 2.需求描述 原本是为了给做unity3d客户端开发的同事提供不定时的消息推送,比如商城购买道具后服务端将道具信息推送给客户端. 本篇文章简化理解,用“相关部门开展活动,向全市人民征集 ...

  3. URL编码与二次encodeURI

    转自:http://foryougeljh.iteye.com/blog/1456706 一般来说,URL只能使用英文字母.阿拉伯数字和某些标点符号,不能使用其他文字和符号.比如,世界上有英文字母的网 ...

  4. Django---drf第一天

    目录 1 序列化组件介绍 2 简单使用 3 序列化类的字段类型 4 序列化字段选项 5 序列化组件修改数据 6 read_only和write_only 7查询所有 8 新增数据 9 删除一个数据 1 ...

  5. React-redux使用

    为什么要使用react-redux 由于redux的store与组件的耦合度太高所以,我们用react官方提供的react-redux可以使两者耦合度降低,更好的实现模块化开发. react-redu ...

  6. day18 装饰器(下)+迭代器+生成器

    目录 一.有参装饰器 1 前提 2 如何使用有参装饰器 3 有参装饰器模板 4 修正装饰器 二.迭代器 1 什么是迭代器 2 为什么要有迭代器 3 如何用迭代器 3.1 可迭代对象 3.2 可迭代对象 ...

  7. Spring Boot 2.3.0正式发布:优雅停机、配置文件位置通配符新特性一览

    当大潮退去,才知道谁在裸泳..关注公众号[BAT的乌托邦]开启专栏式学习,拒绝浅尝辄止.本文 https://www.yourbatman.cn 已收录,里面一并有Spring技术栈.MyBatis. ...

  8. 手把手撸套框架-ORM框架的选择

    目录 一,为什么选择SqlSugar? 在.net core ORM框架中,能选择的方案其实有很多,包括以下方案: 1,EF-Core 2,Dapper 3,FreeSql 4,SqlSugar 为什 ...

  9. EF中延迟加载的那些事

    延迟加载又称懒加载,通俗一点就是关联了一个对象,不用的时候不去查这个对象,当调用的时候再组织sql去查出这个对象的相关内容. 一.在使用EF时,我们会发现借助于框架生成的实体类中的的导航属性通常是标记 ...

  10. vue : 使用stylus less (包括sublime插件支持)

    版本: vue 2.5.2 webpack 3.6.0 先说stylus. 用npm装个包. npm install stylus stylus-loader --save-dev 然后在.vue文件 ...