一代神题啊orz(至少是以前年代的神题吧)

块状树

复杂度nsqrtnlogn

真是exciting

还没有卡时限

话不多说直接上代码

(最近解锁了记事本写代码的技能...感觉越来越依赖OJ调试了...啊感觉写代码准确率高了不少qwq)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <cstdlib>
#include <algorithm>
#include <vector>
#define N 200006
#define M 400006 using namespace std;
inline int read(){
int ret=0;char ch=getchar();
while (ch<'0'||ch>'9') ch=getchar();
while ('0'<=ch&&ch<='9'){
ret=ret*10-48+ch;
ch=getchar();
}
return ret;
} const int KK=400;
vector<int> seq[N]; struct edge{
int adj,next;
edge(){}
edge(int _adj,int _next):adj(_adj),next(_next){}
} e[M];
int n,g[N],m;
void AddEdge(int u,int v){
e[++m]=edge(v,g[u]);g[u]=m;
e[++m]=edge(u,g[v]);g[v]=m;
}
int w[N]; vector<int> nxt[N];
int fa[N],bl[N],sz[N],cnt,top[N];
void refresh(int u,int p){
for (;p>0&&seq[u][p]<seq[u][p-1];--p)swap(seq[u][p],seq[u][p-1]);
for (;p<sz[u]-1&&seq[u][p]>seq[u][p+1];++p)swap(seq[u][p],seq[u][p+1]);
}
void newnode(int u){
if (sz[bl[fa[u]]]==KK){
sz[bl[u]=++cnt]=0;
top[cnt]=u;
}
else bl[u]=bl[fa[u]];
++sz[bl[u]];
}
void dfs(int u){
newnode(u);
for (int i=g[u];i;i=e[i].next){
int v=e[i].adj;
if (v==fa[u]) continue;
fa[v]=u;
dfs(v);
}
}
void dfs_pre(int u){
seq[bl[u]].push_back(w[u]);++sz[bl[u]];
for (int i=g[u];i;i=e[i].next)if (fa[e[i].adj]==u){
int v=e[i].adj;
if (bl[v]==bl[u]) dfs_pre(v);
else nxt[bl[u]].push_back(bl[v]);
}
}
void prepare(int id){
seq[id].clear();vector<int>(seq[id]).swap(seq[id]);
nxt[id].clear();vector<int>(nxt[id]).swap(nxt[id]);
sz[id]=0;
dfs_pre(top[id]);
sort(seq[id].begin(),seq[id].end());
} int solve(int u,int lmt){
int l=-1,r=sz[u],mid;
while (l+1<r){
mid=l+r>>1;
if (seq[u][mid]<=lmt) l=mid;
else r=mid;
}
int ret=sz[u]-l-1;
for (int j=nxt[u].size()-1;j>=0;--j) ret+=solve(nxt[u][j],lmt);
return ret;
}
int query(int u,int lmt){
if (bl[u]!=bl[fa[u]]) return solve(bl[u],lmt);
int ret=w[u]>lmt;
for (int i=g[u];i;i=e[i].next)if (fa[e[i].adj]==u)ret+=query(e[i].adj,lmt);
return ret;
} void modify(int u,int x){
int p;
for (int i=0;i<sz[bl[u]];++i)
if (seq[bl[u]][i]==w[u]){p=i;break;}
w[u]=x;seq[bl[u]][p]=x;
refresh(bl[u],p);
} void create(int u,int x){
AddEdge(u,++n);fa[n]=u;w[n]=x;
int tmp=cnt;
newnode(n);
seq[bl[n]].push_back(w[n]);
refresh(bl[n],sz[bl[n]]-1);
if (tmp<cnt) nxt[bl[u]].push_back(cnt);
} void dfs_update(int u,int last,int now){
bl[u]=now;
for (int i=g[u];i;i=e[i].next)if (fa[e[i].adj]==u)
if (bl[e[i].adj]==last) dfs_update(e[i].adj,last,now);
} void cut(int u){
int lst=bl[u];
if (bl[fa[u]]!=bl[u]){
int f=bl[fa[u]];
for (vector<int>::iterator it=nxt[f].begin();it!=nxt[f].end();++it)
if ((*it)==lst){nxt[f].erase(it);break;}
fa[u]=0;return;
}
top[++cnt]=u;
fa[u]=0;
dfs_update(u,lst,cnt);
prepare(lst);
prepare(cnt);
} int main(){
n=read();
memset(g,0,sizeof(g));m=1;
for (int i=1;i<n;++i) AddEdge(read(),read());
for (int i=1;i<=n;++i) w[i]=read();
fa[1]=0;bl[0]=0;sz[0]=KK;cnt=0;
dfs(1);
int lastans=0;
for (int i=1;i<=cnt;++i) prepare(i);
for (int Q=read();Q;Q--){
int op=read(),u=read()^lastans,x;
if (op<3) x=read()^lastans;
else cut(u);
if (op==0) printf("%d\n",lastans=query(u,x));
else if (op==1) modify(u,x);
else if (op==2) create(u,x);
}
return 0;
}

  

bzoj3731: Gty的超级妹子树的更多相关文章

  1. 【块状树】bzoj3731 Gty的超级妹子树

    带 加点 删边的块状树. 加点在 bzoj3720 说过. 删边其实就是块顶打标记,记录其属于哪棵树,防止在dfs搜集答案时跑到别的树上. 然后暴力把所在块拆开. 好像用邻接表存图,直接在vector ...

  2. BZOJ 3731: Gty的超级妹子树

    3731: Gty的超级妹子树 Time Limit: 7 Sec  Memory Limit: 32 MBSubmit: 346  Solved: 96[Submit][Status][Discus ...

  3. bzoj3731: Gty的超级妹子树(树分块)

    传送门 分块树,代码参考了Manchery的 具体细节还是看代码好了 这题卡常……注意常数写好点…… //minamoto #include<iostream> #include<c ...

  4. bzoj Gty的超级妹子树 块状树

    Gty的超级妹子树 Time Limit: 7 Sec  Memory Limit: 32 MBSubmit: 500  Solved: 122[Submit][Status][Discuss] De ...

  5. BZOJ3720 Gty的妹子树

    Description 我曾在弦歌之中听过你, 檀板声碎,半出折子戏. 舞榭歌台被风吹去, 岁月深处尚有余音一缕…… Gty神(xian)犇(chong)从来不缺妹子…… 他来到了一棵妹子树下,发现每 ...

  6. BZOJ 3720 gty的妹子树

    块状树裸题 块状树: 首先对树进行分块,分出的每一块都是一个连通块 通常的分块的方式如下: 1.父亲所在块不满,分到父亲所在块中 2.父亲所在块满,自己单独开一个块 (貌似有更为优越的分块方式? 注意 ...

  7. 3720: Gty的妹子树

    3720: Gty的妹子树 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1440  Solved: 482[Submit][Status][Disc ...

  8. Gty的妹子树(bzoj 3720)

    Description 我曾在弦歌之中听过你, 檀板声碎,半出折子戏. 舞榭歌台被风吹去, 岁月深处尚有余音一缕…… Gty神(xian)犇(chong)从来不缺妹子…… 他来到了一棵妹子树下,发现每 ...

  9. [BZOJ 3731] Gty的超级妹子树 (树分块)

    [BZOJ 3731] Gty的超级妹子树 (树分块) 题面 给出一棵树(或森林),每个点都有一个值.现在有四种操作 1.查询x子树里>y的值有多少个 2.把点x的值改成y 3.添加一个新节点, ...

随机推荐

  1. ObjectAnimator属性动画应用demo

    感谢慕课网--eclipse_xu 布局文件:activity_main.xml <FrameLayout xmlns:android="http://schemas.android. ...

  2. 【代码笔记】iOS-向服务器传JSON数据的两种方式

    一,代码. - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. ...

  3. readonly

    readonly 关键字是可以在字段上使用的修饰符.  当字段声明包括 readonly 修饰符时,该声明引入的字段赋值只能作为声明的一部分出现,或者出现在同一类的构造函数中. 示例     在此示例 ...

  4. Linux NetHogs监控工具介绍

    NetHogs介绍 NetHogs是一款开源.免费的,终端下的网络流量监控工具,它可监控Linux的进程或应用程序的网络流量.NetHogs只能实时监控进程的网络带宽占用情况.NetHogs支持IPv ...

  5. SQL SERVER 中如何用脚本管理作业

    在SQL SERVER中用脚本管理作业,在绝大部分场景下,脚本都比UI界面管理作业要高效.简洁.打个简单的比方,如果你要查看作业的运行时长,如果用UI界面查看,100个作业,你就得在历史记录里面至少查 ...

  6. Java实现不同的WebService 调用方式

    请求过程分析: 1.使用get方式获取wsdl文件,称为握手 2.使用post发出请求 3.服务器响应成功 几种监听工具: http watch Web Service explorer eclips ...

  7. 烂泥:Postfix邮件服务器搭建之软件安装与配置

    本文由ilanniweb提供友情赞助,首发于烂泥行天下 想要获得更多的文章,可以关注我的微信ilanniweb Postfix邮件服务器的搭建需要使用到几个软件,分别是cyrus-sasl.postf ...

  8. 推荐一款 chrome SSH 插件 - Secure Shell

    http://blog.csdn.net/jizhongchun/article/details/8519413 导读:我就是一个Chrome Fans.最近发现一款google官方出的SSH插件 - ...

  9. amCharts图表中的JavaScript中文注释引起的浏览器兼容性问题

    近期用amCharts做图表.一切都很顺利,然后演示的时候掉链子了,平时开发的时候都是用的火狐和谷歌,加上这种图表框架本来就号称兼容性极好,也没有在ie上测试,演示的机器上恰巧用的是ie11,发现一个 ...

  10. 使用Struts框架,实现用户登陆功能

    前言:本篇文章是本人这周学习的一个小结,在自我总结的同时,希望也能够给其他同学带来一点帮助.本文主要知识是参照书本上的知识点以及网上其他博客文章,在上机操练后的所得,具体源码主要来自http://bl ...