用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. SVD分解求解旋转矩阵

    1.设是两组Rd空间的点集,可根据这两个点集计算它们之间的旋转平移信息. 2.设R为不变量,对T求导得: 令 则 将(4)带入(1)得: 令 则 (相当于对原来点集做减中心点预处理,再求旋转量) 3. ...

  2. ZOJ 1002:Fire Net(DFS+回溯)

    Fire Net Time Limit: 2 Seconds      Memory Limit: 65536 KB Suppose that we have a square city with s ...

  3. 一次scrapy失败的提示信息:由于连接方在一段时间后没有正确答复或连接的主机没有反 应,连接尝试失败

    2017-10-31 19:09:26 [scrapy.extensions.logstats] INFO: Crawled 8096 pages (at 67 pages/min), scraped ...

  4. 为移动端而设计的bootstrap的使用

    一.下载 --bs ---css ----bootstrap.css ----bootstrap.min.css ---fonts ---js ----bootstrap.js ----jquery. ...

  5. URL编码表(收集到的,为了方便查看)

    URL编码表

  6. 铁三测试题——权限、你是管理员吗?——WP

    权限 [题目描述]:你是管理员吗? [解题链接]:http://ctf4.shiyanbar.com/web/root/index.php 首先看题,提到“权限”,“管理员”,这就是说涉及到管理员的账 ...

  7. web服务器和数据库服务器分离的优势

    一般我们服务器都是分开的,网页服务器.数据服务器单独配置. web服务器不掉,那么就可以正常使用,data服务器掉了,那么web还可以坚持一会. 如果是web服务器掉了,那么就上不去了,不过有一些设置 ...

  8. hdu2609 How many 字典树+最小表示法

    Give you n ( n < 10000) necklaces ,the length of necklace will not large than 100,tell meHow many ...

  9. 企业wiki之confluence安装部署(linux)及其破解

    系统环境(虚拟机) centos6.5   2G运行内存,30g硬盘,cpu最好也分配两个或多个,因为我在安装过程中发现很卡,cpu占用率几乎占满 需要用到的安装包和文件可以在这里找 链接:https ...

  10. zabbix入门之使用QQ邮箱接受报警信息

    首先说明我使用的是3.2版本的zabbix 既然要发邮件到QQ邮箱报警,那么在centos7上就肯定需要安装发送邮件的软件了 安装应用yum install mailx sendmail -y接着修改 ...