思路:

恶心的数据结构题……

首先 我们 链剖 把树 变成序列 再 套一个 区间 第K大就好了……

复杂度(n*log^4n)

//By SiriusRen
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define N 88888
#define inf 100000000
int n,q,first[N],next[N*2],v[N*2],t[N],tot,op,xx,yy;
int fa[N],son[N],deep[N],top[N],siz[N],cnt,ch[N];
int root[N*40],size;
struct Treap{int ch[2],sz,cnt,v,rnd;}tr[N*40];
void Upd(int k){tr[k].sz=tr[tr[k].ch[0]].sz+tr[tr[k].ch[1]].sz+tr[k].cnt;}
void Rot(int &k,bool f){int t=tr[k].ch[f];tr[k].ch[f]=tr[t].ch[!f],tr[t].ch[!f]=k,Upd(k),Upd(t),k=t;}
void Insert(int &k,int num){
if(!k){k=++size;tr[k].sz=tr[k].cnt=1,tr[k].rnd=rand();tr[k].v=num;return;}
tr[k].sz++;
if(tr[k].v==num){tr[k].cnt++;return;}
bool f=num>tr[k].v;
Insert(tr[k].ch[f],num);
if(tr[tr[k].ch[f]].rnd<tr[k].rnd)Rot(k,f);
}
void Del(int &k,int num){
if(tr[k].v==num){
if(tr[k].cnt>1)tr[k].cnt--,tr[k].sz--;
else if(tr[k].ch[0]*tr[k].ch[1]==0)k=max(tr[k].ch[0],tr[k].ch[1]);
else Rot(k,tr[tr[k].ch[0]].rnd>tr[tr[k].ch[1]].rnd),Del(k,num);
}
else tr[k].sz--,Del(tr[k].ch[num>tr[k].v],num);
}
int get_rank(int k,int num){
if(!k)return 0;
if(tr[k].v==num)return tr[tr[k].ch[1]].sz;
else if(tr[k].v<num)return get_rank(tr[k].ch[1],num);
else return get_rank(tr[k].ch[0],num)+tr[tr[k].ch[1]].sz+tr[k].cnt;
}
void insert(int l,int r,int pos,int num,int wei){
Insert(root[pos],wei);
if(l==r)return;
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<num)insert(mid+1,r,rson,num,wei);
else insert(l,mid,lson,num,wei);
}
void change(int l,int r,int pos,int num,int wei){
Del(root[pos],t[xx]),Insert(root[pos],wei);
if(l==r)return;
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<num)change(mid+1,r,rson,num,wei);
else change(l,mid,lson,num,wei);
}
int query(int l,int r,int pos,int L,int R,int num){
if(l>=L&&r<=R)return get_rank(root[pos],num);
int mid=(l+r)>>1,lson=pos<<1,rson=pos<<1|1;
if(mid<L)return query(mid+1,r,rson,L,R,num);
else if(mid>=R)return query(l,mid,lson,L,R,num);
else return query(l,mid,lson,L,R,num)+query(mid+1,r,rson,L,R,num);
}
void Add(int x,int y){v[tot]=y,next[tot]=first[x],first[x]=tot++;}
void add(int x,int y){Add(x,y),Add(y,x);}
void dfs(int x){
siz[x]=1;
for(int i=first[x];~i;i=next[i])
if(v[i]!=fa[x]){
fa[v[i]]=x,deep[v[i]]=deep[x]+1;
dfs(v[i]),siz[x]+=siz[v[i]];
if(siz[v[i]]>siz[son[x]])son[x]=v[i];
}
}
void dfs2(int x,int tp){
top[x]=tp,ch[x]=++cnt;
insert(1,n,1,cnt,t[x]);
if(son[x])dfs2(son[x],tp);
for(int i=first[x];~i;i=next[i])
if(v[i]!=fa[x]&&v[i]!=son[x])
dfs2(v[i],v[i]);
}
int find(int x,int y,int num){
int fx=top[x],fy=top[y],tmp=0;
while(fx!=fy){
if(deep[fx]<deep[fy])swap(fx,fy),swap(x,y);
tmp+=query(1,n,1,ch[fx],ch[x],num);
x=fa[fx],fx=top[x];
}
if(deep[x]>deep[y])swap(x,y);
return tmp+query(1,n,1,ch[x],ch[y],num);
}
void b_srch(){
int l=0,r=inf,ans;
while(l<=r){
int mid=(l+r)>>1;
if(find(xx,yy,mid)>=op)l=mid+1;
else ans=mid,r=mid-1;
}
if(!ans)puts("invalid request!");
else printf("%d\n",ans);
}
int main(){
memset(first,-1,sizeof(first));
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)scanf("%d",&t[i]);
for(int i=1;i<n;i++)scanf("%d%d",&xx,&yy),add(xx,yy);
dfs(1),dfs2(1,1);
for(int i=1;i<=q;i++){
scanf("%d%d%d",&op,&xx,&yy);
if(op)b_srch();
else change(1,n,1,ch[xx],yy),t[xx]=yy;
}
}

BZOJ 1146 二分+链剖+线段树+treap的更多相关文章

  1. BZOJ-1036 树的统计Count 链剖线段树(模板)=(树链剖分+线段树)

    潇爷昨天刚刚讲完...感觉得还可以...对着模板打了个模板...还是不喜欢用指针.... 1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec Memory Lim ...

  2. BZOJ 2836 树链剖分+线段树

    思路: 链剖+线段树裸题 重链的标号就是DFS序 所以查子树的时候每回就 query(change[x],change[x]+size[x]-1) 就好了 剩下的应该都会吧.. //By Sirius ...

  3. Gym - 101848C Object-Oriented Programming (树链剖分+线段树+动态开点)

    C. Object-Oriented Programming time limit per test 3.0 s memory limit per test 1024 MB input standar ...

  4. BZOJ.1758.[WC2010]重建计划(分数规划 点分治 单调队列/长链剖分 线段树)

    题目链接 BZOJ 洛谷 点分治 单调队列: 二分答案,然后判断是否存在一条长度在\([L,R]\)的路径满足权值和非负.可以点分治. 对于(距当前根节点)深度为\(d\)的一条路径,可以用其它子树深 ...

  5. 【bzoj2402】陶陶的难题II 分数规划+树链剖分+线段树+STL-vector+凸包+二分

    题目描述 输入 第一行包含一个正整数N,表示树中结点的个数.第二行包含N个正实数,第i个数表示xi (1<=xi<=10^5).第三行包含N个正实数,第i个数表示yi (1<=yi& ...

  6. BZOJ 3672[NOI2014]购票(树链剖分+线段树维护凸包+斜率优化) + BZOJ 2402 陶陶的难题II (树链剖分+线段树维护凸包+分数规划+斜率优化)

    前言 刚开始看着两道题感觉头皮发麻,后来看看题解,发现挺好理解,只是代码有点长. BZOJ 3672[NOI2014]购票 中文题面,题意略: BZOJ 3672[NOI2014]购票 设f(i)f( ...

  7. bzoj 4196 [Noi2015]软件包管理器 (树链剖分+线段树)

    4196: [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2852  Solved: 1668[Submit][Sta ...

  8. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

  9. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

随机推荐

  1. BZOJ 1195 [HNOI2006]最短母串 (Trie图+状压+bfs最短路)

    BZOJ1195 LOJ10061 题目大意:给你$n$个模式串,求一个最短且字典序最小的文本串并输出这个串,$n<=12,len<=50$ 首先对所有模式串构造$Trie$图,$Trie ...

  2. ansible搭建mysql主主模式

    ansible是新出现的自动化运维工具,基于Python开发,集合了众多运维工具(puppet.cfengine.chef.func.fabric)等优点,实现了批量系统配置.批量程序部署.批量运行命 ...

  3. Java基础学习总结(45)——JAVA单元测试工具比较

    1.简介 jtest是parasoft公司推出的一款针对java语言的自动化白盒测试工具,它通过自动实现java的单元测试和代码标准校验,来提高代码的可靠性.Jtest先分析每个java类,然后自动生 ...

  4. Extjs4.2 tooltip 提示宽度问题解决

    在Extjs4.2 的tooltip 提示,宽度被限制在了40px,感觉非常别扭,是个BUG,解决的方法,在ext-all-debug.js或ext-all.js中,找到例如以下的代码: Ext.de ...

  5. m_Orchestrate learning system---二十六、动态给封装好的控件添加属性

    m_Orchestrate learning system---二十六.动态给封装好的控件添加属性 一.总结 一句话总结:比如我现在封装好了ueditor控件,我外部调用这个控件,因为要写数据到数据库 ...

  6. [poj 3904] sky code 解题报告(组合计算+容斥原理)

    题目链接:http://poj.org/problem?id=3904 题目大意: 给出一个数列,询问从中取4个元素满足最大公约数为1的方案数 题解: 很显然,ans=总的方案数-最大公约数大于1的4 ...

  7. POJ 2528 线段树

    坑: 这道题的坐标轴跟普通的坐标轴是不一样的-- 此题的坐标轴 标号是在中间的-- 线段树建树的时候就不用[l,mid][mid,r]了(这样是错的) 直接[l,mid][mid+1,r]就OK了 D ...

  8. Kali linux2.0里Metasploit的服务类型探测

    不多说,直接上干货! 在MSF终端中,可以输入search name:_version命令查看所有可用的服务查点模块 该命令的执行结果如下: root@kali:~# msfconsole ..... ...

  9. CMake入门之创建一个基于PCL的最小工程

    最近在学习PCL,借助Cmake可省去繁琐的添加包含目录和依赖库操作. 一个典型的CMakeLists.txt内容通常为: cmake_minimum_required(VERSION 2.6 FAT ...

  10. PHP——下载图片到本地代码

    <?php //获取网页图片 $url = "http://qlogo2.store.qq.com/qzone/393183837/393183837/50"; $curl ...