[jzoj 6086] [GDOI2019模拟2019.3.26] 动态半平面交 解题报告 (set+线段树)
题目链接:
https://jzoj.net/senior/#main/show/6086
题目:
题解:
- 一群数字的最小公倍数就是对它们质因数集合中的每个质因数的指数取$max$然后相乘
- 这样的子树查询一般都与$dfs$序有关
- 不妨把一个质因数$p$拆分成$p^1,p^2,p^3...$这样若干种颜色,每种颜色对答案的贡献都是$p$
- 我们从另一个角度来考虑如何处理“不同的数”。先不管深度,考虑两个点权相等的节点$u$和$v$,点权为$val$,他们自己的贡献是使得所有子树内包含他的节点答案乘以$val$,现在考虑重复了的贡献,同时包含$u$和$v$的节点答案被乘了两次,即包含$lca(u,v)$的节点答案需要被除去一个$val$。
- 多个节点的时候,只需按$dfs$序排序,相邻两个的$lca$处除即可。现在我们要考虑深度,只需要将询问离线并按深度排序,节点按深度排序后一个一个加入即可。维护点权相同的点可以用$set$,维护$dfs$序用线段树。这是一个很经典的做法
- 在线的话,把线段树可持久化即可
代码:
#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<cmath>
#include<set>
#include<map>
using namespace std;
typedef long long ll; const int N=1e5+;
const int M=1e7+;
const int mo=;
int n,tot;
int a[N],head[N];
set <int> s[N*];
map<int,int>hsh;
struct EDGE
{
int to,nxt;
}edge[N<<];
inline int read()
{
char ch=getchar();int s=,f=;
while (ch<''||ch>'') {if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<='') {s=(s<<)+(s<<)+ch-'';ch=getchar();}
return s*f;
}
int cnt;
int prime[M],mn[M],vis[M];
void pre()
{
mn[]=;
for (int i=;i<M;i++)
{
if (!vis[i]) prime[++cnt]=i,mn[i]=i;
for (int j=;j<=cnt&&prime[j]*i<M;j++)
{
vis[prime[j]*i]=;mn[prime[j]*i]=prime[j];
if (i%prime[j]==) break;
}
}
}
int qpow(int a,int b)
{
int re=;
for (;b;b>>=,a=1ll*a*a%mo) if (b&) re=1ll*re*a%mo;
return re;
}
void add(int u,int v)
{
edge[++tot]=(EDGE){v,head[u]};
head[u]=tot;
}
int tim;
int fa[N][],st[N],ed[N],dep[N],tid[N];
void dfs(int x,int p)
{
dep[x]=dep[p]+;
st[x]=++tim;tid[tim]=x;
fa[x][]=p;
for (int i=;i<=;i++) fa[x][i]=fa[fa[x][i-]][i-];
for (int i=head[x];i;i=edge[i].nxt)
{
int y=edge[i].to;
if (y==p) continue;
dfs(y,x);
}
ed[x]=tim;
}
int lca(int x,int y)
{
if (dep[x]<dep[y]) swap(x,y);
for (int i=;i>=;i--) if (dep[fa[x][i]]>=dep[y]) x=fa[x][i];
if (x==y) return x;
for (int i=;i>=;i--) if (fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][];
}
bool cmp(const int &a,const int &b) {return dep[a]<dep[b];}
int idx;
int get(int x)
{
if (!hsh[x]) hsh[x]=++idx;
return hsh[x];
}
int sz;
int rt[N],mul[N*],ls[N*],rs[N*];
void ins(int &o,int lst,int l,int r,int x,int y)
{
o=++sz;
mul[o]=1ll*mul[lst]*y%mo;
ls[o]=ls[lst];rs[o]=rs[lst];
if (l==r) return;
int mid=l+r>>;
if (x<=mid) ins(ls[o],ls[lst],l,mid,x,y);
else ins(rs[o],rs[lst],mid+,r,x,y);
}
int query(int o,int l,int r,int x,int y)
{
if (l>=x&&r<=y) return mul[o];
int mid=l+r>>,re=;
if (x<=mid) re=1ll*re*query(ls[o],l,mid,x,y)%mo;
if (y>mid) re=1ll*re*query(rs[o],mid+,r,x,y)%mo;
return re;
}
int b[N];
int main()
{
freopen("half.in","r",stdin);
freopen("half.out","w",stdout);
pre();
int k=read();n=read();
for (int i=;i<=n;i++) a[i]=read(),b[i]=i;
for (int i=;i<n;i++)
{
int u=read(),v=read();
add(u,v);add(v,u);
}
dfs(,);
mul[]=;
sort(b+,b++n,cmp);
set<int>::iterator it1,it2,it3;
for (int i=;i<=n;i++)
{
int u=b[i],d=dep[u],tmp=a[u];
rt[d]=rt[dep[b[i-]]];
while (tmp>)
{
int t=mn[tmp],it=qpow(t,mo-),z=;
while (tmp%t==)
{
tmp/=t;
z*=t;
int y=get(z);
s[y].insert(st[u]);
it2=s[y].lower_bound(st[u]);
it1=it2;
if (it1!=s[y].begin()) --it1;
it3=it2;
++it3;
ins(rt[d],rt[d],,n,st[u],t);
int u1=,u2=;
if (it2!=s[y].begin())
{
u1=tid[*it1];int L=lca(u1,u);
ins(rt[d],rt[d],,n,st[L],it);
}
if (it3!=s[y].end())
{
u2=tid[*it3];int L=lca(u2,u);
ins(rt[d],rt[d],,n,st[L],it);
}
if (u1&&u2)
{
int L=lca(u1,u2);
ins(rt[d],rt[d],,n,st[L],t);
}
}
}
}
for (int i=dep[b[n]]+;i<=n;i++) rt[i]=rt[i-];
int q=read(),ans=;
while (q--)
{
int u=read()^(k*ans),d=min(n,dep[u]+read()^(k*ans));
printf("%d\n",query(rt[d],,n,st[u],ed[u]));
}
return ;
}
[jzoj 6086] [GDOI2019模拟2019.3.26] 动态半平面交 解题报告 (set+线段树)的更多相关文章
- [jzoj 6092] [GDOI2019模拟2019.3.30] 附耳而至 解题报告 (平面图转对偶图+最小割)
题目链接: https://jzoj.net/senior/#main/show/6092 题目: 知识点--平面图转对偶图 在求最小割的时候,我们可以把平面图转为对偶图,用最短路来求最小割,这样会比 ...
- [jzoj 4528] [GDOI2019模拟2019.3.26] 要换换名字 (最大权闭合子图)
题目链接: https://jzoj.net/senior/#contest/show/2683/0 题目: 题解: 不妨枚举一个点,让两颗树都以这个点为根,求联通块要么点数为$0$,要么包括根(即联 ...
- [jzoj 6087] [GDOI2019模拟2019.3.26] 获取名额 解题报告 (泰勒展开+RMQ+精度)
题目链接: https://jzoj.net/senior/#main/show/6087 题目: 题解: 只需要统计$\prod_{i=l}^r (1-\frac{a_i}{x})$ =$exp(\ ...
- [JZOJ6075]【GDOI2019模拟2019.3.20】桥【DP】【线段树】
Description N,M<=100000,S,T<=1e9 Solution 首先可以感受一下,我们把街道看成一行,那么只有给出的2n个点的纵坐标是有用的,于是我们可以将坐标离散化至 ...
- [jzoj 6093] [GDOI2019模拟2019.3.30] 星辰大海 解题报告 (半平面交)
题目链接: https://jzoj.net/senior/#contest/show/2686/2 题目: 题解: 说实话这题调试差不多花了我十小时,不过总算借着这道题大概了解了计算几何的基础知识 ...
- [jzoj 6101] [GDOI2019模拟2019.4.2] Path 解题报告 (期望)
题目链接: https://jzoj.net/senior/#main/show/6101 题目: 题解: 设$f_i$表示从节点$i$到节点$n$的期望时间,$f_n=0$ 最优策略就是如果从$i, ...
- [jzoj 6080] [GDOI2019模拟2019.3.23] IOer 解题报告 (数学构造)
题目链接: https://jzoj.net/senior/#main/show/6080 题目: 题意: 给定$n,m,u,v$ 设$t_i=ui+v$ 求$\sum_{k_1+k_2+...+k_ ...
- [jzoj 6084] [GDOI2019模拟2019.3.25] 礼物 [luogu 4916] 魔力环 解题报告(莫比乌斯反演+生成函数)
题目链接: https://jzoj.net/senior/#main/show/6084 https://www.luogu.org/problemnew/show/P4916 题目: 题解: 注: ...
- [JZOJ 5908] [NOIP2018模拟10.16] 开荒(kaihuang)解题报告 (树状数组+思维)
题目链接: https://jzoj.net/senior/#contest/show/2529/1 题目: 题目背景:尊者神高达作为一个萌新,在升级路上死亡无数次后被一只大黄叽带回了师门.他加入师门 ...
随机推荐
- PHP7添加swoole扩展
swoole需要php版本在7.0以上. 1.进入php目录中的bin目录下,通过pecl指令进行安装. cd /usr/local/php7/bin [root@localhost bin]# pw ...
- 2. Add Two Numbers[M]两数相加
题目 You are given two non-empty linked lists representing two non-negative integers. The digits are s ...
- Java 系列之spring学习--springmvc搭建(四)
一.建立java web 项目 二.添加jar包 spring jar包下载地址http://repo.spring.io/release/org/springframework/spring/ 2. ...
- Java 系列之Filter(一)
一.过滤器 过滤器就是在源数据和目的数据之间起过滤作用的中间组件.它可以截取客户端和资源之间的请求和响应信息,并且对这些信息进行过滤. 二.应用场景 1.对用户请求进行统一认证 2.对用户的访问请求进 ...
- PopupWindow实现点击外部不消失
View contentView = LayoutInflater.from(MainActivity.this).inflate(R.layout.alert_ip, null); final Po ...
- iOS-Core-Animation-Advanced-Techniques/12-性能调优/性能调优.md
性能调优 代码应该运行的尽量快,而不是更快 - 理查德 在第一和第二部分,我们了解了Core Animation提供的关于绘制和动画的一些特性.Core Animation功能和性能都非常强大,但如果 ...
- 第十二章 Python网络编程
socket编程 socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口.它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket ...
- C语言基本语法——结构体、联合和枚举
一.结构体 1.什么是结构体 2.结构体语法格式 3.结构体所占内存空间 4.结构体成员赋值 二.联合 1.什么是联合 2.联合语法格式 三.枚举 1.什么是枚举 2.枚举语法格式 一.结构体 1.什 ...
- 基于 OSGi 的面向服务的组件编程
作者:曹 羽中 (caoyuz@cn.ibm.com), 软件工程师, IBM中国开发中心 出处:http://www.ibm.com/developerworks/cn/opensource/os- ...
- java中的string trim具体有什么用处。。。
去掉字符串首尾空格 防止不必要的空格导致错误public class test{ public static void main(String[] args) { String str = " ...