3637: Query on a tree VI

Time Limit: 8 Sec  Memory Limit: 1024 MB
Submit: 206  Solved: 38
[Submit][Status][Discuss]

Description

You are given a tree (an acyclic undirected connected graph) with n nodes. The tree nodes are numbered from 1 to n.

Each node has a color, white or black. All the nodes are black initially.

We will ask you to perfrom some instructions of the following form:

  • 0 u : ask for how many nodes are connected to u, two nodes are connected iff all the node on the path from u to v (inclusive u and v) have a same color.
  • 1 u : toggle the color of u(that is, from black to white, or from white to black).
 

Input

The first line contains a number n denoted how many nodes in the tree(1 ≤ n ≤ 105). The next n - 1 lines, each line has two numbers (u,  v) describe a edge of the tree(1 ≤ u,  v ≤ n). The next line contains a number m denoted how many operations we are going to process(1 ≤ m ≤ 105). The next m lines, each line describe a operation (t,  u) as we mentioned above(0 ≤ t ≤ 1, 1 ≤ u ≤ n).

Output

 

For each query operation, output the corresponding result.

Sample Input

5
1 2
1 3
1 4
1 5
3
0 1
1 1
0 1

Sample Output

5
1

HINT

Source

  这道题常数卡的有点紧,我树链剖分用一棵线段树存就TLE了,每个链分别建线段树才行。

  考虑将每一个同色块的答案保存在这一块深度最浅的那一个点(这是一个很好的思路),我们考虑如何维护即可,对于每一个点,我们维护f[now][0/1]表示当前点如果取白色/黑色,所在的子树中与这个点同色的联通块大小。

  每次颜色修改只会影响到当前点到根节点路径上的一段。而且还是路径加减一个数,这可以用链剖维护。

  询问时只用跳到当前联通块最上方的点,然后输出该点所存的f值即可。

  

  AC600了,lalala~~

#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define MAXN 101000
#define MAXV MAXN*2
#define MAXE MAXV*2
#define MAXT MAXN*4
#define lch sgt[now].lc
#define rch sgt[now].rc
#define smid ((l+r)>>1)
#define INF 0x3f3f3f3f
struct Edge
{
int np;
Edge *next;
}E[MAXE],*V[MAXV];
int tope=-;
void addedge(int x,int y)
{
E[++tope].np=y;
E[tope].next=V[x];
V[x]=&E[tope];
} int q[MAXN];
int pnt[MAXN];
int siz[MAXN];
int son[MAXN],top[MAXN],pos[MAXN],apos[MAXN],dfstime;
void bfs(int now)
{
int head=-,tail=;
Edge *ne;
q[]=now;
pnt[now]=;
while (head<tail)
{
now=q[++head];
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==pnt[now])continue;
pnt[ne->np]=now;
q[++tail]=ne->np;
}
}
for (int i=tail;i>=;i--)
{
now=q[i];
siz[now]=;
int mxsiz=;
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==pnt[now])continue;
siz[now]+=siz[ne->np];
if (siz[ne->np]>mxsiz)
{
mxsiz=now;
son[now]=ne->np;
}
}
}
}
int stack[MAXN],tops=-;
void dfs(int now)
{
Edge *ne;
stack[++tops]=now;
top[now]=now;
while (~tops)
{
now=stack[tops--];
pos[now]=++dfstime;
apos[dfstime]=now;
for (ne=V[now];ne;ne=ne->next)
{
if (ne->np==pnt[now] || ne->np==son[now])continue;
stack[++tops]=ne->np;
top[ne->np]=ne->np;
}
if (son[now])
{
stack[++tops]=son[now];
top[son[now]]=top[now];
}
}
}
int col[MAXN];
int ptra[MAXN];
struct sgt_node
{
int lc,rc;
int sum[];
int pls[];
int val[];
}sgt[MAXT];
int topt=;
void make_plus(int now,int c,int d)
{
sgt[now].val[c]+=d;
sgt[now].pls[c]+=d;
}
void down(int now)
{
if (sgt[now].pls[])
{
make_plus(lch,,sgt[now].pls[]);
make_plus(rch,,sgt[now].pls[]);
sgt[now].pls[]=;
}
if (sgt[now].pls[])
{
make_plus(lch,,sgt[now].pls[]);
make_plus(rch,,sgt[now].pls[]);
sgt[now].pls[]=;
}
}
int Build_sgt(int l,int r)
{
int now=++topt;
sgt[now].val[]=sgt[now].val[]=sgt[now].pls[]=sgt[now].pls[]=;
sgt[now].sum[]=;
sgt[now].sum[]=;
if (l==r)
{
ptra[l]=now;
sgt[now].val[]=siz[apos[l]];
sgt[now].val[]=;
return now;
}
lch=Build_sgt(l,smid);
rch=Build_sgt(smid+,r);
return now;
}
pair<int,int> Query_sgt(int now,int l,int r,int pos)
{
if (l==r)
return make_pair(sgt[now].val[],sgt[now].val[]);
down(now);
if (pos<=smid)
return Query_sgt(lch,l,smid,pos);
else
return Query_sgt(rch,smid+,r,pos);
}
void Modify_sgt(int now,int l,int r,int x,int y,int c,int d)
{
if (l==x && r==y)
{
make_plus(now,c,d);
return ;
}
down(now);
if (y<=smid)
return Modify_sgt(lch,l,smid,x,y,c,d);
else if (smid<x)
return Modify_sgt(rch,smid+,r,x,y,c,d);
else
{
Modify_sgt(rch,smid+,r,smid+,y,c,d);
Modify_sgt(lch,l,smid,x,smid,c,d);
}
}
void Modify_sgt2(int now,int l,int r,int pos)
{
if (l==r)
return swap(sgt[now].sum[],sgt[now].sum[]);
down(now);
if (pos<=smid)
Modify_sgt2(lch,l,smid,pos);
else
Modify_sgt2(rch,smid+,r,pos);
sgt[now].sum[]=sgt[lch].sum[]+sgt[rch].sum[];
sgt[now].sum[]=sgt[lch].sum[]+sgt[rch].sum[];
}
int Scan_sgt(int now,int l,int r,int x,int y,int c)
{
if (l==x && r==y)
{
if (sgt[now].sum[c]==(r-l+))
{
return l;
}else if (sgt[now].sum[c]==)
{
return -;
}else
{
down(now);
int ret=Scan_sgt(rch,smid+,r,smid+,y,c);
if (ret==smid+)
{
ret=Scan_sgt(lch,l,smid,x,smid,c);
if (ret==-)return smid+;
else return ret;
}else return ret;
}
}
down(now);
if (y<=smid)
return Scan_sgt(lch,l,smid,x,y,c);
else if (smid<x)
return Scan_sgt(rch,smid+,r,x,y,c);
else
{
int ret=Scan_sgt(rch,smid+,r,smid+,y,c);
if (ret==smid+)
{
ret=Scan_sgt(lch,l,smid,x,smid,c);
if (ret==-)return smid+;
else return ret;
}else return ret;
}
}
int spos[MAXN],tpos[MAXN];
int troot[MAXN];
int Swim_up(int x)
{
int rpos=pos[x];
int c=col[x];
while (x)
{
int y=Scan_sgt(troot[top[x]],spos[top[x]],tpos[top[x]],pos[top[x]],pos[x],c);
if (y==-)break;
else if (y!=pos[top[x]])
{
rpos=y;break;
}else
{
rpos=y;
x=pnt[top[x]];
}
}
return apos[rpos];
}
int main()
{
freopen("input.txt","r",stdin);
freopen("output.txt","w",stdout);
int n,m;
int x,y,z;
scanf("%d",&n);
for (int i=;i<n;i++)
{
scanf("%d%d",&x,&y);
addedge(x,y);
addedge(y,x);
}
bfs();
dfs();
for (int i=;i<=n;i++)
spos[i]=INF,tpos[i]=-INF;
for (int i=;i<=n;i++)
spos[top[i]]=min(spos[top[i]],pos[i]);
for (int i=;i<=n;i++)
tpos[top[i]]=max(tpos[top[i]],pos[i]);
for (int i=;i<=n;i++)
if (top[i]==i)
troot[i]=Build_sgt(spos[i],tpos[i]);
scanf("%d",&m);
int opt;
for (int i=;i<=n;i++)col[i]=;
for (int i=;i<m;i++)
{
scanf("%d%d",&opt,&x);
if (opt==)
{
int rpt=Swim_up(x);
pair<int,int> res=Query_sgt(troot[top[rpt]],spos[top[rpt]],tpos[top[rpt]],pos[rpt]);
if (col[x]==)
printf("%d\n",res.first);
else
printf("%d\n",res.second);
}else
{
pair<int,int> res=Query_sgt(troot[top[x]],spos[top[x]],tpos[top[x]],pos[x]);
int p=pnt[x];
int c=col[p];
int d,d2;
if (col[p]== && col[x]==)d=-res.second,d2=res.first;
else if (col[p]== && col[x]==)d=res.second,d2=-res.first;
else if (col[p]== && col[x]==)d=res.first,d2=-res.second;
else d=-res.first,d2=res.second;
if (p)
{
sgt[ptra[pos[p]]].val[c^]+=d2;
int a=Swim_up(p);
a=pnt[a];
if (!a)a=;
while (true)
{
if (top[p]==top[a])
{
Modify_sgt(troot[top[a]],spos[top[a]],tpos[top[a]],pos[a],pos[p],c,d);
break;
}
Modify_sgt(troot[top[p]],spos[top[p]],tpos[top[p]],pos[top[p]],pos[p],c,d);
p=pnt[top[p]];
}
}
Modify_sgt2(troot[top[x]],spos[top[x]],tpos[top[x]],pos[x]);
col[x]^=;
}
}
}

bzoj 3637: Query on a tree VI 树链剖分 && AC600的更多相关文章

  1. SPOJ QTREE6 Query on a tree VI 树链剖分

    题意: 给出一棵含有\(n(1 \leq n \leq 10^5)\)个节点的树,每个顶点只有两种颜色:黑色和白色. 一开始所有的点都是黑色,下面有两种共\(m(1 \leq n \leq 10^5) ...

  2. [BZOJ 3637]Query on a tree VI

    偶然看见了这题,觉得自己 QTREE.COT 什么的都没有刷过的真是弱爆了…… 一道思路很巧妙的题,终于是在约大爷的耐心教导下会了,真是太感谢约大爷了. 这题显然是树链剖分,但是链上维护的东西很恶心. ...

  3. QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树

    Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...

  4. spoj 375 Query on a tree(树链剖分,线段树)

      Query on a tree Time Limit: 851MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Sub ...

  5. SPOJ 375 Query on a tree(树链剖分)(QTREE)

    You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, ...

  6. SPOJ QTREE - Query on a tree 【树链剖分模板】

    题目链接 引用到的大佬博客 代码来自:http://blog.csdn.net/jinglinxiao/article/details/72940746 具体算法讲解来自:http://blog.si ...

  7. [SPOJ375]QTREE - Query on a tree【树链剖分】

    题目描述 给你一棵树,两种操作. 修改边权,查找边权的最大值. 分析 我们都知道,树链剖分能够维护点权. 而且每一条边只有一个,且唯一对应一个儿子节点,那么就把信息放到这个儿子节点上. 注意,lca的 ...

  8. SPOJ 375 Query on a tree(树链剖分)

    https://vjudge.net/problem/SPOJ-QTREE 题意: 给出一棵树,树上的每一条边都有权值,现在有查询和更改操作,如果是查询,则要输出u和v之间的最大权值. 思路: 树链剖 ...

  9. 【SPOJ Query on a tree 】 (树链剖分)

    http://acm.hust.edu.cn/vjudge/problem/13013 题意: 有一棵N个节点的树(1<=N<=10000),N-1条边,边的编号为1~N-1,每条边有一个 ...

随机推荐

  1. asp网站发布步骤总结

    1.在VS2012中打开索要发布的网站,初始页可重命名为index.html或default.apx. 2.点击  生成>生成“网站”,然后“发布网站”. 3.进行发布设置: (1 配置文件 ( ...

  2. Span flag详解

    在android中,如果要实现text的各种样式,图文混排等,简单的样式可以靠几个不同的textview来拼成,而复杂的样式要求,用不同的textview来拼接则不太现 实.这时候就spannable ...

  3. Unite Beijing 2015大型活动

    摘要:2015年,我做的最疯狂的事情:网友见面会—去北京参加Unite Beijing 2015大会. 正文:记得,上次在北京参加大型活动还是2008年前–传统电信行业的巅峰时期:那时移动互联网.An ...

  4. XPath 初步讲解

    2016-05-05 XPath是JavaScript 中节点查找手段,ie9以后的版本才支持w3c标准,其他浏览器基本支持.在e8之前的浏览器,通过基于 activeX的xml dom对象实现. 为 ...

  5. jqGrid Tree

    CSS: <!--jqGrid--><link rel="stylesheet" href="plugins/jqgird/css/ui.jqgrid. ...

  6. 分享一个难得的YiBo微博客户端应用源码Android版

    今天给大家分享一款,YiBo微博客户端应用源码,这是一款专为Android用户打造的聚合型微博客户端,完美支持新浪微博.腾讯微博.搜狐微博.网易微博和饭否五个微博平台,界面清爽,使用简单轻巧,支持多账 ...

  7. 在Centos6.5安装MySQL

    在阐述安装过程之前一定要再写一句,Centos7上安装MySQL是默认安装的MariaDB,因为在Centos7中用MariaDB代替了mysql数据库. linux安装软件很简单,有的时候只有一句话 ...

  8. nutch安装配置

    http://nlp.solutions.asia/?p=180 http://www.promenade.me/archives/146 环境 ubuntu 12.04 sql建表 CREATE D ...

  9. web网页的表单排版利器--960css

    表单排版样式 960css 前言 一般web网页的表单排版,大家都习惯用table排版,自己需要根据实际需要去定义TR和TD,很多时候对于TD的高宽度.是否合并行,合并列,都要去做一些处理,这些都是比 ...

  10. 【Winform】无法嵌入互操作类型

    在使用Interop.SQLDMO进行数据库还原操作时,在vs2010编译时出现:无法嵌入互操作类型“……”,请改用适用的接口的解决方法 解决方案: 选中项目中引入的dll,鼠标右键,选择属性,把“嵌 ...