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. Spring(3.2.3) - Beans(11): depends-on

    大多数情况下,Bean 之间的依赖非常直接:被依赖的 Bean 作为属性.在 XML 配置文件中最常见的就是使用 <ref/> 元素.在一些特殊情况下,Bean 之间的依赖不够直接.比如, ...

  2. HTTP - 持久连接

    Web 客户端经常会打开到同一个站点的连接.比如,一个 Web 页面上的大部分内嵌图片通常都是来自同一个 Web 站点,而且相当一部分指向其他对象的超链接通常都指向同一个站点.因此,初始化了对某服务器 ...

  3. Asp.net MVC 4 Html帮助类

    Html帮助类 used to render (modify and output) HTML form elements 用来渲染HTML表单元素(修改和输出) Html.ActionLink 输出 ...

  4. Android实现双进程守护 (转)

    做过android开发的人应该都知道应用会在系统资源匮乏的情况下被系统杀死!当后台的应用被系统回收之后,如何重新恢复它呢?网上对此问题有很多的讨论.这里先总结一下网上流传的各种解决方案,看看这些办法是 ...

  5. 北大ACM(POJ1753-Flip Game)

    Question:http://poj.org/problem?id=1753 问题点:穷举. #include <iostream> using namespace std; ][];/ ...

  6. Entity Framework 6.1-Model First

    原文:Entity Framework 6.1-Model First Model First-顾名思义,就是先创建EF数据模型,通过数据模型生成数据库的EF创建方式. 步骤. 1.新建一个DAL的文 ...

  7. (转)微软开放了.NET 4.5.1的源代码

    微软开放了.NET 4.5.1的源代码 .NET Reference Source发布了beta版,可以在线浏览.NET Framework 4.5.1的源代码,并且可以通过配置,在Visual St ...

  8. Map的三种遍历方式

    对于Map的三种方式遍历 1.keySet() 2.values() 3.entrySet()三种方式得到Set之后,都可以使用 foreach或者iterator, 不能使用for,因为数据结构决定 ...

  9. Poj OpenJudge 百练 2602 Superlong sums

    1.Link: http://poj.org/problem?id=2602 http://bailian.openjudge.cn/practice/2602/ 2.Content: Superlo ...

  10. swing画太极图案源码

    package org.open.swing.taiji; /** * @(#)Taichi.java * * * @author * @version 1.00 2007/6/12 */ impor ...