看到这个标题立刻想到:、

“绝地科学家,八倍不屏息啊,八百里外把头打啊...”

首先我们发现如果只考虑第二个操作,这棵树就是假的,我们可以直接莫队解决

如果考虑换根的话...可以把一个操作换成小于等于9个操作就可以了

当然怎么换,有一些非常恶心的分类讨论

嘤嘤嘤

YNOI 题是好题 但是要卡常 首先要fread & fwrite

然后需要wxh的莫队写法

然后要算一下分块大小

sqrt(q_size) -> (n / sqrt(q_size))

40 -> 100

嘤嘤嘤

#include<bits/stdc++.h>
#define LL long long
using namespace std;
inline char nc()
{
static char buf[] , *p1 , *p2;
return p1 == p2 && (p2 = (p1 = buf) + fread(buf , , , stdin) , p1 == p2) ? EOF : *p1 ++ ;
}
inline int read()
{
int ret = ; char ch = nc();
while(!isdigit(ch)) ch = nc();
while(isdigit(ch)) ret = ((ret + (ret << )) << ) + (ch ^ '') , ch = nc();
return ret;
}
char pbuf[] , *pp = pbuf;
inline void push(const char ch)
{
if(pp == pbuf + ) fwrite(pbuf , , , stdout) , pp = pbuf;
*pp ++ = ch;
}
inline void write(long long x)
{
static char sta[];
int top = ;
if(!x) push('');
while(x) sta[++top] = x % ^ '' , x /= ;
while(top) push(sta[top -- ]);
push('\n');
}
const int maxn = ;
int n,m,rt;
int qx;
int a[maxn],vi[maxn];
int q_size;
int first[maxn],to[maxn << ],nx[maxn << ],cnt;
inline void add(int u,int v)
{
to[++cnt] = v;
nx[cnt] = first[u];
first[u] = cnt;
}
inline void ins(int u,int v){add(u,v);add(v,u);}
struct Q
{
int l,r,bl,id,opt;
Q(){};
Q(int _l,int _r,int _id,int _opt){l = min(_l,_r),r = max(_l,_r),id = _id,opt = _opt;}
bool operator < (const Q &b)const
{
if(bl == b.bl)
{
if(bl & )
return r < b.r;
return r > b.r;
}
return l < b.l;
}
}qs[maxn * ];
int fa[maxn][],dep[maxn],ind[maxn],oud[maxn],reh[maxn],dfn;
inline void dfs(int x)
{
ind[x] = ++dfn;reh[dfn] = a[x];
for(int i=;i<=;i++)
fa[x][i] = fa[fa[x][i - ]][i - ];
for(int i=first[x];i;i=nx[i])
{
if(to[i] == fa[x][])continue;
dep[to[i]] = dep[x] + ;
fa[to[i]][] = x;
dfs(to[i]);
}oud[x] = dfn;
}
LL ans[maxn * ];
LL now;int cnt_x[maxn],cnt_y[maxn];
inline int go_anc(int x , int y)
{
int i;
for(i = ; ~i ; i -- )
if(dep[y] - dep[x] > ( << i))
y = fa[y][i];
return y;
}
int xpos[],ypos[],opt_x[],opt_y[];
int main()
{
freopen("1.in","r",stdin);
freopen("www.out","w",stdout);
int tx,ty;
n = read(),m = read();
for(int i=;i<=n;i++)vi[i] = a[i] = read();
sort(vi + ,vi + n + );
for(int i=;i<=n;i++)a[i] = lower_bound(vi + ,vi + n + ,a[i]) - vi;
for(int i=;i<=n;i++)
{
int u = read(),v = read();
ins(u,v);
}dfs(rt = );
//return 0;
for(int i=;i<=m;i++)
{
int t = read(),x = read();
if(t == ){rt = x;continue;}
int y = read(),z;q_size++;
tx = ty = ;
if(x == rt) xpos[++tx] = n , opt_x[tx] = ;
else if(ind[rt] < ind[x] || ind[rt] > oud[x]) xpos[++tx] = oud[x] , opt_x[tx] = , xpos[++tx] = ind[x] - , opt_x[tx] = -;
else z = go_anc(x , rt) , xpos[++tx] = n , opt_x[tx] = , xpos[++tx] = oud[z] , opt_x[tx] = - , xpos[++tx] = ind[z] - , opt_x[tx] = ; if(y == rt) ypos[++ty] = n , opt_y[ty] = ;
else if(ind[rt] < ind[y] || ind[rt] > oud[y]) ypos[++ty] = oud[y] , opt_y[ty] = , ypos[++ty] = ind[y] - , opt_y[ty] = -;
else z = go_anc(y , rt) , ypos[++ty] = n , opt_y[ty] = , ypos[++ty] = oud[z] , opt_y[ty] = - , ypos[++ty] = ind[z] - , opt_y[ty] = ; for(int j=;j<=tx;j++)
for(int k=;k<=ty;k++)
if(xpos[j] && ypos[k])
qs[++qx] = Q(xpos[j] , ypos[k] , q_size , opt_x[j] * opt_y[k]);
}
int si = (int)(n / sqrt(qx));
for(int i=;i<=qx;i++)qs[i].bl = (qs[i].l - ) / si;
sort(qs + ,qs + qx + );
int l = ,r = ;
for(int i=;i<=qx;i++)
{
while(l < qs[i].l){l++;now += cnt_y[reh[l]],cnt_x[reh[l]]++;}
while(r < qs[i].r){r++;now += cnt_x[reh[r]],cnt_y[reh[r]]++;}
while(l > qs[i].l){cnt_x[reh[l]]--;now -= cnt_y[reh[l]];l--;}
while(r > qs[i].r){cnt_y[reh[r]]--;now -= cnt_x[reh[r]];r--;}
ans[qs[i].id] += now * qs[i].opt;
}
for(int i=;i<=q_size;i++)write(ans[i]);
fwrite(pbuf , , pp - pbuf , stdout);
}

YNOI2016 这是我自己的发明的更多相关文章

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

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

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

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

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

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

  4. bzoj4940: [Ynoi2016]这是我自己的发明

    用dfs序把询问表示成询问dfs序的两个区间中的信息 拆成至多9个询问(询问dfs序的两个前缀),对这些询问用莫队处理,时间复杂度$O(n\sqrt{m})$ #include<bits/std ...

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

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

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

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

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

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

  8. 洛谷P4689 [Ynoi2016]这是我自己的发明(树上莫队+树链剖分)

    题目描述 您正在打galgame,然后突然家长进来了,于是您假装在写数据结构题: 给一个树,n 个点,有点权,初始根是 1. m 个操作,每次操作: 1.将树根换为 x. 2.给出两个点 x,y,从  ...

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

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

随机推荐

  1. python 微信跳一跳和源码解读

    刚好周末,想研究一下前阵子很火的微信跳一跳 下面进入正文. 本文适用对象为WIN10系统,安卓用户.目的在于让丝毫没有接触过Python的小伙伴都能成功运行,如果你恰好是这样的对象,那么跟着我开始操作 ...

  2. windy数(简单数位DP)

    1026: [SCOI2009]windy数 Time Limit: 1 Sec  Memory Limit: 162 MBSubmit: 6306  Solved: 2810[Submit][Sta ...

  3. 【python】-- 函数非固定参数,返回值(return)

    函数非固定参数 1.默认参数: 代码如下: def information_register(name,age,country,sex): print("----注册信息------&quo ...

  4. springboot错误页面处理

    springboot作为微服务的便捷框架,在错误页面处理上也有了一些新的处理,不同于之前的pringmvc500的页面处理是比较简单的,用java config或者xml的形式,定义如下的Bean即可 ...

  5. 我的Android进阶之旅------>关于android:layout_weight属性的一个面试题

    最近碰到一个面试题,按照下图,由Button和EditText组成的界面下厨布局代码,解决这题目需要使用android:layout_weight的知识. 首先分析上图所示的界面可以看成一下3个部分. ...

  6. (转)Spring 缓存EhCacheFactoryBean

    Spring使用Cache 从3.1开始,Spring引入了对Cache的支持.其使用方法和原理都类似于Spring对事务管理的支持.Spring Cache是作用在方法上的,其核心思想是这样的:当我 ...

  7. LeetCode:颜色分类【75】

    LeetCode:颜色分类[75] 题目描述 给定一个包含红色.白色和蓝色,一共 n 个元素的数组,原地对它们进行排序,使得相同颜色的元素相邻,并按照红色.白色.蓝色顺序排列. 此题中,我们使用整数 ...

  8. ELK日志分析系统-Logstack

    ELK日志分析系统 作者:Danbo 2016-*-* 本文是学习笔记,参考ELK Stack中文指南,链接:https://www.gitbook.com/book/chenryn/kibana-g ...

  9. P3768 【简单的数学题】

    P3768 [简单的数学题] \(Ans=\sum ^{n}_{i=1}\sum ^{n}_{j=1}ijgcd(i,j)\) \(=\sum ^{n}_{i=1}\sum ^{n}_{j=1}ij\ ...

  10. mysql中的内连接,外连接实例详解

    内连接: 只连接匹配的行左外连接: 包含左边表的全部行(不管右边的表中是否存在与它们匹配的行),以及右边表中全部匹配的行右外连接: 包含右边表的全部行(不管左边的表中是否存在与它们匹配的行),以及左边 ...