询问的化我们可以建主席树。然后修改?,树套树。。。,最后插入?炸了。

所以我们对操作进行分块。

我们先对整棵树建一个主席树。修改,插入我们先记录下来。然后询问的时候先对主席树查询,然后暴力遍历我们记录下来的修改插入操作。每\(\sqrt{m}\)次操作后我们重新构建一个主席树。这样我们保证了重建主席树和询问的总复杂度为\(O(nlogn\sqrt{m})\)然后就把这道题解决了。

有一个难办的事就是如何记录修改和插入的操作。可以使每次询问的时候我们可以知道修改和插入是否在\(u\)的子树中以便我们判断是否要让这些修改和询问产生贡献。因为没考虑到可以询问插入的节点,在多次尝试后我决定维护一个\(f[i][j]\)代表i向上跳\(i^j\)的深度到达的节点。处理询问的时候我们对于每一个修改和插入都跳到和u一个深度看是否相等。

当然还要记录一些常规的信息比如这个点被修改之前的权值什么的。。。

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=101000;
int head[N],cnt;
int n,m,ans,a[N],b[N],CNT,more;
int be[N],ed[N],dep[N],fa[N][25],tot,id[N],top,w[N],from[N];
int root[N],ch[N*20][2],sum[N*20],num;
struct edge{
int to,nxt;
}e[N*2];
inline void add_edge(int u,int v){
cnt++;
e[cnt].nxt=head[u];
e[cnt].to=v;
head[u]=cnt;
}
inline void add(int l,int r,int x,int pre,int &now){
now=++num;
sum[now]=sum[pre]+1;
ch[now][0]=ch[pre][0];
ch[now][1]=ch[pre][1];
if(l==r)return;
int mid=(l+r)>>1;
if(x>mid)add(mid+1,r,x,ch[pre][1],ch[now][1]);
else add(l,mid,x,ch[pre][0],ch[now][0]);
}
inline int check(int l,int r,int L,int R,int pre,int now){
if(l==L&&r==R)return sum[now]-sum[pre];
int mid=(l+r)>>1;
if(L>mid)return check(mid+1,r,L,R,ch[pre][1],ch[now][1]);
else if(R<=mid)return check(l,mid,L,R,ch[pre][0],ch[now][0]);
else return check(l,mid,L,mid,ch[pre][0],ch[now][0])+check(mid+1,r,mid+1,R,ch[pre][1],ch[now][1]);
}
inline void dfs(int u,int f){
be[u]=++tot;
dep[u]=dep[f]+1;
add(1,n,lower_bound(b+1,b+1+n,a[u])-b,root[be[u]-1],root[be[u]]);
fa[u][0]=f;
for(int i=1;i<=20;i++)fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=head[u];i;i=e[i].nxt){
int v=e[i].to;
if(v==f)continue;
dfs(v,u);
}
ed[u]=tot;
}
inline bool judge(int x,int to){
for(int i=20;i>=0;i--)
if(dep[fa[x][i]]>=dep[to])x=fa[x][i];
if(x==to)return true;
else return false;
}
inline int read(){
int sum=0,f=1;char ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){sum=(sum<<1)+(sum<<3)+ch-'0';ch=getchar();}
return sum*f;
}
int main(){
n=read();
for(int i=1;i<n;++i){
int u=read(),v=read();
add_edge(u,v);add_edge(v,u);
}
for(int i=1;i<=n;++i)a[i]=read();
m=read();
int Block=sqrt(m*25);
while(m--){
int type=read(),u=read()^ans,x=read()^ans;
if(CNT==0){
tot=0;top=0;num=0;n+=more;more=0;
for(int i=1;i<=n;i++)b[i]=a[i];
sort(b+1,b+1+n);
dfs(1,1);
}
if(type==0){
if(u<=n){
int tmp=upper_bound(b+1,b+1+n,x)-b;
if(tmp<=n)ans=check(1,n,tmp,n,root[be[u]-1],root[ed[u]]);
else ans=0;
}
else ans=0;
for(int i=1;i<=top;++i)
if(judge(id[i],u)){
if(from[i]>x)ans--;
if(w[i]>x)ans++;
}
for(int i=n+1;i<=n+more;++i){
if(judge(i,u)){
if(w[i]>x)ans++;
}
}
printf("%d\n",ans);
CNT++;
}
else if(type==1){
++top;
w[top]=x;from[top]=a[u];id[top]=u;
++CNT;
a[u]=x;
}
else{
++more;
add_edge(n+more,u);
add_edge(u,n+more);
a[n+more]=x;
fa[n+more][0]=u;dep[n+more]=dep[u]+1;
for(int i=1;i<=20;i++)fa[n+more][i]=fa[fa[n+more][i-1]][i-1];
w[n+more]=x;
++CNT;
}
if(CNT==Block)CNT=0;
}
return 0;
}

luogu P2137 Gty的妹子树(分块,主席树)的更多相关文章

  1. hdu4417 Super Mario (树状数组/分块/主席树)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4417 题目大意:给定一个长度为n的序列,有m个询问,每次询问包含l,r,h,即询问区间[l,r]小于等 ...

  2. poj 2104 K-th Number 划分树,主席树讲解

    K-th Number Input The first line of the input file contains n --- the size of the array, and m --- t ...

  3. 归并树 划分树 可持久化线段树(主席树) 入门题 hdu 2665

    如果题目给出1e5的数据范围,,以前只会用n*log(n)的方法去想 今天学了一下两三种n*n*log(n)的数据结构 他们就是大名鼎鼎的 归并树 划分树 主席树,,,, 首先来说两个问题,,区间第k ...

  4. BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树

    BZOJ_2588_Spoj 10628. Count on a tree_树剖+主席树 题意: 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastan ...

  5. 【BZOJ4771】七彩树(主席树)

    [BZOJ4771]七彩树(主席树) 题面 BZOJ 题解 如果没有深度限制,每次只询问子树内的颜色个数,除了树套树\(dfs\)序加前驱或者后继强行二维数点之外,还有这样一种做法: 把所有相同颜色的 ...

  6. 洛谷P3248 树 [HNOI2016] 主席树+倍增+分治

    正解:主席树+倍增+分治 解题报告: 传送门! 首先看到这题会想到之前考过的这题 但是那题其实简单一些,,,因为那题只要用个分治+预处理就好,只是有点儿思维难度而已 这题就不一样,因为它说了是按照原树 ...

  7. POJ 2761 Feed the dogs(平衡树or划分树or主席树)

    Description Wind loves pretty dogs very much, and she has n pet dogs. So Jiajia has to feed the dogs ...

  8. 【题解】BZOJ3489 A Hard RMQ problem(主席树套主席树)

    [题解]A simple RMQ problem 占坑,免得咕咕咕了,争取在2h内写出代码 upd:由于博主太菜而且硬是要用指针写两个主席树,所以延后2hQAQ upd:由于博主太菜而且太懒所以他决定 ...

  9. POJ 2104 K-th Number(分桶,线段树,主席树)

    一道比较经典的数据结构题.可以用多种方式来做. 一,分桶法(平方分解). 根据数字x的大小和区间内不大于x的数字数量cnt的单调性,可知第k大数kth对应的cnt应该满足cnt≥k, 且kth是满足条 ...

随机推荐

  1. nginx 日志配置不生效的问题

    log_format 有个默认的日志格式: log_format combined '$remote_addr - $remote_user [$time_local] ' ' "$requ ...

  2. Java自定义属性注解

    代码: import static java.lang.annotation.RetentionPolicy.RUNTIME; import java.lang.annotation.ElementT ...

  3. 关于layui.laypage.render 刷新首页没有分页问题

    前言: 最近写项目遇到一个问题,就是使用vue里的layui.laypage.render 分页时,刷新首页会只有一页,但后台传来的数据是有50多页的,所有的数据也都一一对应,调了好久debug,终于 ...

  4. (4)pyspark---dataframe清理

    1.交叉表(crosstab): pandas中也有,常和pivot_table比较. 查看家庭ID与评分的交叉表: 2.处理缺失值:fillna withColumn:新增一列数据 cast : 用 ...

  5. [USACO 2009 Feb Gold] Fair Shuttle (贪心+优先队列)

    题目大意:有N个站点的轻轨站,有一个容量为C的列车起点在1号站点,终点在N号站点,有K组牛群,每组数量为Mi(1≤Mi≤N),行程起点和终点分别为Si和Ei(1≤Si<Ei≤N).计算最多有多少 ...

  6. Linux学习01

    Linux学习第一天 1.使用VM安装RHEL7.0 具体参见刘遄老师的<Linux就该怎么学>https://www.linuxprobe.com/chapter-01.html 2.R ...

  7. 再识Quartz

    在之前的项目中使用过Quartz,但都是基于XML配置定义任务的.目前一个项目应用需要对任务进行创建.暂停.删除等动态管理.所以再次在网上翻了翻,再来好好重新认识下Quartz. 名词解释: sche ...

  8. Git中的工作区(Working Directory)、暂存区(stage)和历史记录区(history)

    今天和git搏斗了一下午,发现了修改的文件一直commit不了.网上查了一下才发现原来git的模型里还有工作区和暂存区的说法. 工作区:在git管理下的正常目录都算是工作区.我们平时的编辑工作都是在工 ...

  9. Spring Security中的MD5盐值加密

    在 spring Security 文档中有这么一句话: "盐值的原理非常简单,就是先把密码和盐值指定的内容合并在一起,再使用md5对合并后的内容进行演算,这样一来,就算密码是一个很常见的字 ...

  10. 洛谷——P3258 [JLOI2014]松鼠的新家

    https://www.luogu.org/problem/show?pid=3258 题目描述 松鼠的新家是一棵树,前几天刚刚装修了新家,新家有n个房间,并且有n-1根树枝连接,每个房间都可以相互到 ...