bzoj3731: Gty的超级妹子树
一代神题啊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的超级妹子树的更多相关文章
- 【块状树】bzoj3731 Gty的超级妹子树
带 加点 删边的块状树. 加点在 bzoj3720 说过. 删边其实就是块顶打标记,记录其属于哪棵树,防止在dfs搜集答案时跑到别的树上. 然后暴力把所在块拆开. 好像用邻接表存图,直接在vector ...
- BZOJ 3731: Gty的超级妹子树
3731: Gty的超级妹子树 Time Limit: 7 Sec Memory Limit: 32 MBSubmit: 346 Solved: 96[Submit][Status][Discus ...
- bzoj3731: Gty的超级妹子树(树分块)
传送门 分块树,代码参考了Manchery的 具体细节还是看代码好了 这题卡常……注意常数写好点…… //minamoto #include<iostream> #include<c ...
- bzoj Gty的超级妹子树 块状树
Gty的超级妹子树 Time Limit: 7 Sec Memory Limit: 32 MBSubmit: 500 Solved: 122[Submit][Status][Discuss] De ...
- BZOJ3720 Gty的妹子树
Description 我曾在弦歌之中听过你, 檀板声碎,半出折子戏. 舞榭歌台被风吹去, 岁月深处尚有余音一缕…… Gty神(xian)犇(chong)从来不缺妹子…… 他来到了一棵妹子树下,发现每 ...
- BZOJ 3720 gty的妹子树
块状树裸题 块状树: 首先对树进行分块,分出的每一块都是一个连通块 通常的分块的方式如下: 1.父亲所在块不满,分到父亲所在块中 2.父亲所在块满,自己单独开一个块 (貌似有更为优越的分块方式? 注意 ...
- 3720: Gty的妹子树
3720: Gty的妹子树 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1440 Solved: 482[Submit][Status][Disc ...
- Gty的妹子树(bzoj 3720)
Description 我曾在弦歌之中听过你, 檀板声碎,半出折子戏. 舞榭歌台被风吹去, 岁月深处尚有余音一缕…… Gty神(xian)犇(chong)从来不缺妹子…… 他来到了一棵妹子树下,发现每 ...
- [BZOJ 3731] Gty的超级妹子树 (树分块)
[BZOJ 3731] Gty的超级妹子树 (树分块) 题面 给出一棵树(或森林),每个点都有一个值.现在有四种操作 1.查询x子树里>y的值有多少个 2.把点x的值改成y 3.添加一个新节点, ...
随机推荐
- Wireshark设置interface 时提示“There are no interfaces on which a capture can be done ”
Wireshark设置interface 时提示“There are no interfaces on which a capture can be done ” 解决方法: 今天在电脑上安装了WIR ...
- 比Ansible更吊的自动化运维工具,自动化统一安装部署自动化部署udeploy 1.0 版本发布
新增功能: 逻辑与业务分离,完美实现逻辑与业务分离,业务实现统一shell脚本开发,由框架统一调用. 并发多线程部署,不管多少台服务器,多少个服务,同时发起线程进行更新.部署.启动. 提高list规则 ...
- SQL SERVER 2012 执行计划走嵌套循环导致性能问题的案例
开发人员遇到一个及其诡异的的SQL性能问题,这段完整SQL语句如下所示: declare @UserId INT declare @PSANo VAR ...
- Linux 磁盘自检介绍
在Linux系统中,有时候重启会耗费非常长的时间,如果你进一步检查细节,就会发现绝大部分时间都耗费在磁盘自检(fsck)上了,有时候遇到时间比较紧急的情况,磁盘自检耗费的时间非常长,真的是让人心焦火急 ...
- 从零自学Hadoop(17):Hive数据导入导出,集群数据迁移下
阅读目录 序 将查询的结果写入文件系统 集群数据迁移一 集群数据迁移二 系列索引 本文版权归mephisto和博客园共有,欢迎转载,但须保留此段声明,并给出原文链接,谢谢合作. 文章是哥(mephis ...
- Unity在Android和iOS中如何调用Native API
本文主要是对unity中如何在Android和iOS中调用Native API进行介绍. 首先unity支持在C#中调用C++ dll,这样可以在Android和iOS中提供C++接口在unity中调 ...
- PHP函数整理(二)
以下均参考自 php.net 1.curl_setopt_array() 此函数为CURL传输会话批量设置选项.这个函数对于需要设置大量的curl选项是非常有用的,不需要重复的调用curl_setop ...
- 【小白的CFD之旅】04 任务
和老蓝见面之后的很长一段时间里,小白都没有接到任何老蓝的消息,再加上课比较多,小白也慢慢适应了白天上课,晚上窝在宿舍打游戏,偶尔也去图书馆看看书的生活,这样宁静的生活持续了差不多两个月.就在老蓝的影子 ...
- MySQL Database on Azure新功能
本月中国版的MySQL Database on Azure发布了两项新功能: 1.主从复制——只读实例 在这之前Azure上的MySQL数据库也是支持主从复制的,但是只能作为on-premises部署 ...
- java进程占用CPU资源过高分析脚本
#!/bin/bash #输入占用CPU较高的进程号 pid=$ if [ -z $pid ] then echo "PID is NULL" exit fi #找到该进程中占用较 ...