2019.02.17 spoj Query on a tree VI(链分治)
传送门
题意简述:给你一棵nnn个黑白点的树,支持改一个点的颜色,询问跟某个点颜色相同的连通块大小。
思路:
还是链分治 233
记fi,0/1f_{i,0/1}fi,0/1表示iii的所有颜色为0/10/10/1的轻儿子在它们子树中颜色相同的连通块大小。
然后这个可以用来询问子树里的答案,但是要询问的东西是针对全局的。
因此我们沿着重链往上跳更新答案,直到某条链中有点跟要问的颜色不一样。
即fif_ifi表示这个东西:

对于这棵树,我们的fB1,0f_{B1,0}fB1,0就等于跟它颜色一样的B2B2B2的子树中颜色为BBB且与B2B2B2连通的连通块大小,即111
而对于fB1,1f_{B1,1}fB1,1由于他的颜色不是WWW,因此fB1,1=0f_{B1,1}=0fB1,1=0。
对于B3B3B3假设重儿子是W3W3W3,那么fB3,0=1+1=2,fB3,1=0f_{B3,0}=1+1=2,f_{B3,1}=0fB3,0=1+1=2,fB3,1=0
这样子就可以用链分治维护要有的信息了。
代码:
#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
const int N=1e5+5;
inline int read(){
int ans=0;
char ch=getchar();
while(!isdigit(ch))ch=getchar();
while(isdigit(ch))ans=(((ans<<2)+ans)<<1)+(ch^48),ch=getchar();
return ans;
}
typedef pair<int,int> pii;
int n,m,fa[N],top[N],bot[N],num[N],pred[N],siz[N],hson[N],tot=0,f[N][2];
vector<int>e[N];
bool col[N];
void dfs1(int p){
siz[p]=1;
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i])==fa[p])continue;
fa[v]=p,dfs1(v),siz[p]+=siz[v];
if(siz[v]>siz[hson[p]])hson[p]=v;
}
}
void dfs2(int p,int tp){
top[p]=tp,bot[tp]=p,pred[num[p]=++tot]=p;
if(!hson[p])return;
dfs2(hson[p],tp);
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i])==fa[p]||v==hson[p])continue;
dfs2(v,v);
}
}
namespace SGT{
#define lc (p<<1)
#define rc (p<<1|1)
#define mid (T[p].l+T[p].r>>1)
struct Val{
int ls,rs;
bool f;
inline void init(const int&x){ls=rs=x;f=x==0?0:1;}
};
struct Node{int l,r;Val s[2];}T[N<<2];
inline Val operator+(const Val&a,const Val&b){
Val ret;
ret.f=a.f&b.f;
ret.ls=a.ls+(a.f?b.ls:0);
ret.rs=b.rs+(b.f?a.rs:0);
return ret;
}
inline void pushup(int p){
T[p].s[0]=T[lc].s[0]+T[rc].s[0];
T[p].s[1]=T[lc].s[1]+T[rc].s[1];
}
inline void Set(int p){
int k=pred[T[p].l];
T[p].s[col[k]].init(f[k][col[k]]+1);
T[p].s[col[k]^1].init(0);
}
inline void build(int p,int l,int r){
T[p].l=l,T[p].r=r;
if(l==r)return;
build(lc,l,mid),build(rc,mid+1,r);
}
inline void update(int p,int k){
if(T[p].l==T[p].r)return Set(p);
update(k<=mid?lc:rc,k),pushup(p);
}
inline Val query(int p,int ql,int qr,bool f){
if(ql<=T[p].l&&T[p].r<=qr)return T[p].s[f];
if(qr<=mid)return query(lc,ql,qr,f);
if(ql>mid)return query(rc,ql,qr,f);
return query(lc,ql,qr,f)+query(rc,ql,qr,f);
}
}
pii dfs3(int tp){
for(ri p=tp;p;p=hson[p]){
for(ri i=0,v;i<e[p].size();++i){
if((v=e[p][i])==fa[p]||v==hson[p])continue;
pii tmp=dfs3(v);
f[p][0]+=tmp.fi,f[p][1]+=tmp.se;
}
SGT::update(1,num[p]);
}
return pii(SGT::query(1,num[tp],num[bot[tp]],0).ls,SGT::query(1,num[tp],num[bot[tp]],1).ls);
}
inline void update(int p){
int ft,tp,bt;
while(p){
ft=fa[top[p]],tp=top[p],bt=bot[tp];
if(ft){
pii tmp=pii(SGT::query(1,num[tp],num[bt],0).ls,SGT::query(1,num[tp],num[bt],1).ls);
f[ft][0]-=tmp.fi,f[ft][1]-=tmp.se;
}
SGT::update(1,num[p]);
if(ft){
pii tmp=pii(SGT::query(1,num[tp],num[bt],0).ls,SGT::query(1,num[tp],num[bt],1).ls);
f[ft][0]+=tmp.fi,f[ft][1]+=tmp.se;
}
p=ft;
}
}
inline int query(int p){
int ft,tp,bt,ret=0,x=p;
SGT::Val tmp;
while(p){
if(col[x]^col[p])break;
ft=fa[top[p]],tp=top[p],bt=bot[tp];
ret=SGT::query(1,num[p],num[bt],col[x]).ls;
if(p^tp){
tmp=SGT::query(1,num[tp],num[p]-1,col[x]),ret+=tmp.rs;
if(!tmp.f)return ret;
}
p=ft;
}
return ret;
}
int main(){
n=read();
for(ri i=1,u,v;i<n;++i)u=read(),v=read(),e[u].push_back(v),e[v].push_back(u);
dfs1(1),dfs2(1,1),SGT::build(1,1,n),dfs3(1);
for(ri tt=read(),x;tt;--tt){
if(read())col[x=read()]^=1,update(x);
else cout<<query(read())<<'\n';
}
return 0;
}
2019.02.17 spoj Query on a tree VI(链分治)的更多相关文章
- 2019.02.17 spoj Query on a tree VII(链分治)
传送门 跟QTREE6QTREE6QTREE6神似,改成了求连通块里的最大值. 于是我们对每条链开一个heapheapheap维护一下即可. MDMDMD终于1A1A1A链分治了. 代码: #incl ...
- 2019.02.17 spoj Query on a tree V(链分治)
传送门 题意简述: 给你一棵nnn个黑白点的树,初始全是黑点. 现在支持给一个点换颜色或者求整颗树中离某个点最近的白点跟这个点的距离. 思路: 考虑链分治维护答案,每个链顶用一个堆来维护答案,然后对于 ...
- 2019.02.16 spoj Query on a tree IV(链分治)
传送门 题意简述: 捉迷藏强化版(带有边权,可以为负数) 思路:好吧这次我们不用点分树,我们用听起来更屌的链分治. 直接把树剖成若干条重链,这样保证从任意一个点跳到根节点是不会跳超过logloglog ...
- SPOJ Query on a tree 树链剖分 水题
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...
- bzoj 3637: Query on a tree VI 树链剖分 && AC600
3637: Query on a tree VI Time Limit: 8 Sec Memory Limit: 1024 MBSubmit: 206 Solved: 38[Submit][Sta ...
- QTREE6 - Query on a tree VI 解题报告
QTREE6 - Query on a tree VI 题目描述 给你一棵\(n\)个点的树,编号\(1\)~\(n\).每个点可以是黑色,可以是白色.初始时所有点都是黑色.下面有两种操作请你操作给我 ...
- SPOJ QTREE Query on a tree 树链剖分+线段树
题目链接:http://www.spoj.com/problems/QTREE/en/ QTREE - Query on a tree #tree You are given a tree (an a ...
- spoj 375 Query on a tree (树链剖分)
Query on a tree You are given a tree (an acyclic undirected connected graph) with N nodes, and edges ...
- Query on a tree——树链剖分整理
树链剖分整理 树链剖分就是把树拆成一系列链,然后用数据结构对链进行维护. 通常的剖分方法是轻重链剖分,所谓轻重链就是对于节点u的所有子结点v,size[v]最大的v与u的边是重边,其它边是轻边,其中s ...
随机推荐
- SSH Secure Shell Client中文乱码的解决方法
http://www.cnblogs.com/52linux/archive/2012/03/24/2415082.html 方案一:修改linux服务器的环境变量 使用linux,在用户根目录下有一 ...
- 谷歌浏览器内核Cef js代码整理(一)
尊重作者原创,未经作者允许不得转载!作者:xtfnpgy,原文地址: https://www.cnblogs.com/xtfnpgy/p/9285359.html 一.js基础知识 <!-- ...
- C#使用ITextSharp操作pdf
在.NET中没有很好操作pdf的类库,如果你需要对pdf进行编辑,加密,模板打印等等都可以选择使用ITextSharp来实现. 第一步:可以点击这里下载,新版本的插件升级和之前对比主要做了这几项重大改 ...
- Spring MVC Controller异常处理总结
在项目开发过程中,经常遇到服务被攻击的情况,虽然接口在设计过程中有相当多的安全措施,例如cookie校验.风控.访问熔断等相关技术保证服务的安全性,不过感觉还是有必要收集分析一下这些攻击请求者,以备为 ...
- Spring整体了解
1.spring原理 内部最核心的就是IOC了,动态注入,让一个对象的创建不用new了,可以自动的生产,这其实就是利用java里的反射,反射其实就是在运行时动态的去创建.调用对象,Spring就是 ...
- leetcode236
class Solution { public: TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) { ...
- 20165304《Java程序设计》第九周学习总结
教材学习内容总结 URL类 URL类是java.net包中的一个重要的类,URL的实例封装着一个统一资源定位符,使用URL创建对象的应用程序称作客户端程序. 一个URL对象通常包含最基本的三部分信息: ...
- model.form使用,配合form的钩子
一次model.form的使用记录,配合form钩子的过程 在写信息采集功能的时候,需要添加资产信息,使用modelform组件减少工作量 官网介绍:版本1.9.https://docs.django ...
- python装饰器补漏
以前写过一篇装饰器文章,觉得少了点东西,今天特来补上,也就是带参数的装饰器,上篇文章写的不严谨 def logger(logs=""): def outer(f): def inn ...
- javascript隐式原型
上图是js原型关系图. javascript是一种基于对象的编程语言,但它与一般面向对象的编程语言不同,因为它没有class类的概念 什么是原型?? 我们每创建一个函数,它就会自带一个原型函数,这个原 ...