用dfs序把询问表示成询问dfs序的两个区间中的信息

拆成至多9个询问(询问dfs序的两个前缀),对这些询问用莫队处理,时间复杂度$O(n\sqrt{m})$

#include<bits/stdc++.h>
typedef long long i64;
const int N=1e5+;
char buf[N],*ptr=buf+,ob[N],*op=ob;
int G(){
if(ptr-buf==)fread(ptr=buf,,,stdin);
return *ptr++;
}
int _(){
int x=;
if(ptr-buf<){
while(*ptr<)++ptr;
while(*ptr>)x=x*+*ptr++-;
}else{
int c=G();
while(c<)c=G();
while(c>)x=x*+c-,c=G();
}
return x;
}
#define fl fwrite(ob,1,op-ob,stdout),op=ob
void pr(i64 x){
if(op-ob>)fl;
int ss[],sp=;
if(!x)*op++=;
while(x)ss[++sp]=x%,x/=;
while(sp)*op++=ss[sp--]+;
*op++=;
}
i64 ans[N*];
int n,m,rt=;
int v[N],vs[N],qc=;
int es[N*],enx[N*],e0[N],ep=;
int fa[N],sz[N],son[N],dep[N],top[N],id[N][],vi[N],idp=;
void f1(int w,int pa){
dep[w]=dep[fa[w]=pa]+;
sz[w]=;
for(int i=e0[w];i;i=enx[i]){
int u=es[i];
if(u==pa)continue;
f1(u,w);
sz[w]+=sz[u];
if(sz[u]>sz[son[w]])son[w]=u;
}
}
void f2(int w,int tp){
id[w][]=++idp;
vi[idp]=v[w];
top[w]=tp;
if(son[w])f2(son[w],tp);
for(int i=e0[w];i;i=enx[i]){
int u=es[i];
if(u!=fa[w]&&u!=son[w])f2(u,u);
}
id[w][]=idp;
}
int up(int x,int y){
int a=top[x],b=top[y];
while(a!=b){
x=fa[a];
if(x==y)return a;
a=top[x];
}
return son[y];
}
bool chk(int w){
return id[w][]<id[rt][]&&id[rt][]<=id[w][];
}
int pos[N],B,qp=;
struct Q{
int l,r,sgn,id;
}qs[N*],qs1[N*],*ls[N],*lp;
int tr[N],tb[N];
i64 s0[N],_ans;
int ts[N][];
inline void inc0(int x){++ts[x][],_ans+=ts[x][];}
inline void dec0(int x){--ts[x][],_ans-=ts[x][];}
inline void inc1(int x){++ts[x][],_ans+=ts[x][];}
inline void dec1(int x){--ts[x][],_ans-=ts[x][];}
void cal(int w,int*a,int&p){
if(w==rt)a[]=n,p=;
else if(id[w][]<id[rt][]&&id[rt][]<=id[w][]){
w=up(rt,w);
a[]=n;
a[]=-id[w][];
a[]=id[w][]-;
p=;
}else{
a[]=id[w][];
a[]=-id[w][];
p=;
}
}
void ins(int a,int b,int id){
if(!(a&&b))return;
int c=;
if(a<)a=-a,c=-c;
if(b<)b=-b,c=-c;
if(a>b)std::swap(a,b);
if(b==n)ans[id]+=c*s0[a];
else qs[qp++]=(Q){a,b,c,id};
}
int main(){
n=_();m=_();
for(int i=;i<=n;++i)v[i]=vs[i]=_();
std::sort(vs+,vs+n+);
for(int i=;i<=n;++i)v[i]=std::lower_bound(vs+,vs+n+,v[i])-vs;
for(int i=,a,b;i<n;++i){
a=_(),b=_();
es[ep]=b;enx[ep]=e0[a];e0[a]=ep++;
es[ep]=a;enx[ep]=e0[b];e0[b]=ep++;
}
f1(,);
f2(,);
for(int i=;i<=n;++i)inc0(vi[i]);
for(int i=;i<=n;++i)inc1(vi[i]),s0[i]=_ans;
_ans=;
memset(ts,,sizeof(ts));
for(int i=;i<=m;++i){
if(_()==)rt=_();
else{
++qc;
int x=_(),y=_();
int xv[],xp,yv[],yp;
cal(x,xv,xp);
cal(y,yv,yp);
for(int a=;a<xp;++a)
for(int b=;b<yp;++b)ins(xv[a],yv[b],qc);
}
}
B=n/sqrt(qp+)*+;
for(int i=;i<=n;++i)pos[i]=i/B; for(int i=;i<qp;++i)++tr[qs[i].r],++tb[pos[qs[i].l]];
lp=qs1;
for(int i=;i<=n;++i)ls[i]=lp,lp+=tr[i];
for(int i=;i<qp;++i)*ls[qs[i].r]++=qs[i];
lp=qs;
for(int i=;i<=pos[n];++i)ls[i]=lp,lp+=tb[i];
for(int i=;i<qp;++i)*ls[pos[qs1[i].l]]++=qs1[i];
for(int i=;i<pos[n];i+=)std::reverse(ls[i],ls[i+]); int L=,R=;
for(int i=;i<qp;++i){
int l=qs[i].l,r=qs[i].r;
while(L<l)inc0(vi[++L]);
while(L>l)dec0(vi[L--]);
while(R<r)inc1(vi[++R]);
while(R>r)dec1(vi[R--]);
ans[qs[i].id]+=qs[i].sgn*_ans;
}
for(int i=;i<=qc;++i)pr(ans[i]);
return fl,;
}

bzoj4940: [Ynoi2016]这是我自己的发明的更多相关文章

  1. bzoj4940 [Ynoi2016]这是我自己的发明 莫队+dfs序

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4940 题解 对于换根操作,处理方法就很套路了. 首先先假定以 \(1\) 为根做一遍 dfs, ...

  2. 【bzoj4940】[Ynoi2016]这是我自己的发明 DFS序+树上倍增+莫队算法

    题目描述 给一个树,n 个点,有点权,初始根是 1. m 个操作,每次操作: 1. 将树根换为 x. 2. 给出两个点 x,y,从 x 的子树中选每一个点,y 的子树中选每一个点,如果两个点点权相等, ...

  3. 【bzoj4940】这是我自己的发明

    Portal --> bzoj4940 Solution (原题这题面到底是..怎么回事啊深深的套路qwq) 感觉自己对根号的算法还是很..没有感觉啊== 实际上这题和bzoj5016没有任何区 ...

  4. 洛谷P4689 [Ynoi2016]这是我自己的发明(莫队,树的dfn序,map,容斥原理)

    洛谷题目传送门 具体思路看别的题解吧.这里只提两个可能对常数和代码长度有优化的处理方法. I 把一个询问拆成\(9\)个甚至\(16\)个莫队询问实在是有点珂怕. 发现询问的一边要么是一个区间,要么是 ...

  5. [Ynoi2016]这是我自己的发明 莫队

    传送门:here 很棒的莫队题啊..... 题意: 有一棵$ n$个点的树,树上每个点有点权,有$ m$次询问: 操作1:给定两个点$ x,y$,求二元组$ (a,b)$的数量,要求$ a$在$ x$ ...

  6. 洛谷P4689 [Ynoi2016]这是我自己的发明 [莫队]

    传送门 ynoi中比较良心不卡常的题. 思路 没有换根操作时显然可以变成dfs序莫队随便搞. 换根操作时一个子树可以变成两段区间的并集,也随便搞搞就好了. 这题完全不卡常,随便过. 代码 #inclu ...

  7. [Ynoi2016]这是我自己的发明(莫队)

    话说这道题数据是不是都是链啊,我不手动扩栈就全 \(RE\)... 不过 \(A\) 了这题还是很爽的,通过昨晚到今天早上的奋斗,终于肝出了这题 其实楼上说的也差不多了,就是把区间拆掉然后莫队瞎搞 弱 ...

  8. YNOI2016 这是我自己的发明

    看到这个标题立刻想到:. “绝地科学家,八倍不屏息啊,八百里外把头打啊...” 首先我们发现如果只考虑第二个操作,这棵树就是假的,我们可以直接莫队解决 如果考虑换根的话...可以把一个操作换成小于等于 ...

  9. Luogu4689 [Ynoi2016]这是我自己的发明 【莫队】

    题目链接:洛谷 又来做Ynoi里面的水题了... 首先换根的话是一个套路,首先以1为根dfs,然后画一画就知道以rt为根,x的子树是什么了.可以拆分为2个dfs连续段. 然后如果要计算\([l_1,r ...

随机推荐

  1. select标签(分组下拉菜单和列表)

    分组下拉菜单和列表标签: <select name=" " > <optgroup label="组1"> <option val ...

  2. HDU - 5421:Victor and String (回文树,支持首尾插入新字符)

    Sample Input 6 1 a 1 b 2 a 2 c 3 4 8 1 a 2 a 2 a 1 a 3 1 b 3 4 Sample Output 4 5 4 5 11 题意:多组输入,开始字符 ...

  3. angular的点击添加

    首先是在js里面我们可以用clone来点击添加一些东西比如列表或者其他的div之类的,但是在angular里面怎么实现点击添加呢? 类似这种: 这样就尴尬了,最少我这样的菜鸟是不知道怎么去写的,网上好 ...

  4. seo:与优化相关的熊掌号

    可以做的有: 站点资源管理 天级收录(提交链接即可) 视频极速服务(暂只针对移动端体验优化)https://ziyuan.baidu.com/college/articleinfo?id=2411 原 ...

  5. L2-008 最长对称子串 (25 分)

    对给定的字符串,本题要求你输出最长对称子串的长度.例如,给定Is PAT&TAP symmetric?,最长对称子串为s PAT&TAP s,于是你应该输出11. 输入格式: 输入在一 ...

  6. (11)模板语言-if判断

    views.py from django.shortcuts import render,HttpResponse # Create your views here. def index(reques ...

  7. python------模块定义、导入、优化 ------->Shelve模块

    1. shelve模块 是一个简单的k,v将内存数据通过文件持久化的模块,可以持久化任何pickle可支持的python数据格式. import shelve import datetime d = ...

  8. mariadb增量备份

    何为增量备份,简单理解就是使用日志记录每天数据库的操作情况,只需要每天把这个日志里的数据库操作还原到数据库中,从而避免每天都进行完全备份,这种情况下,每周进行一次完全备份即可 首先我们需要配置以下ma ...

  9. wget命令的使用

    wget是在命令行下载文件的命令 -c 断点续传,用于大文件的下载或者网络不稳定的情况下,一般不写也可以 -P 指定下载到那个目录(是大写的P) 举例 [root@bogon local]# wget ...

  10. Compoxure example 应用说明

    Compoxure 官方提供了一个demo应用,包含了cache,error,layout 等功能 环境准备 demo 使用docker-compose 运行 clone 代码 git clone h ...