bzoj 3637: Query on a tree VI 树链剖分 && AC600
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
1 2
1 3
1 4
1 5
3
0 1
1 1
0 1
Sample Output
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的更多相关文章
- SPOJ QTREE6 Query on a tree VI 树链剖分
题意: 给出一棵含有\(n(1 \leq n \leq 10^5)\)个节点的树,每个顶点只有两种颜色:黑色和白色. 一开始所有的点都是黑色,下面有两种共\(m(1 \leq n \leq 10^5) ...
- [BZOJ 3637]Query on a tree VI
偶然看见了这题,觉得自己 QTREE.COT 什么的都没有刷过的真是弱爆了…… 一道思路很巧妙的题,终于是在约大爷的耐心教导下会了,真是太感谢约大爷了. 这题显然是树链剖分,但是链上维护的东西很恶心. ...
- QTREE3 spoj 2798. Query on a tree again! 树链剖分+线段树
Query on a tree again! 给出一棵树,树节点的颜色初始时为白色,有两种操作: 0.把节点x的颜色置反(黑变白,白变黑). 1.询问节点1到节点x的路径上第一个黑色节点的编号. 分析 ...
- spoj 375 Query on a tree(树链剖分,线段树)
Query on a tree Time Limit: 851MS Memory Limit: 1572864KB 64bit IO Format: %lld & %llu Sub ...
- 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, ...
- SPOJ QTREE - Query on a tree 【树链剖分模板】
题目链接 引用到的大佬博客 代码来自:http://blog.csdn.net/jinglinxiao/article/details/72940746 具体算法讲解来自:http://blog.si ...
- [SPOJ375]QTREE - Query on a tree【树链剖分】
题目描述 给你一棵树,两种操作. 修改边权,查找边权的最大值. 分析 我们都知道,树链剖分能够维护点权. 而且每一条边只有一个,且唯一对应一个儿子节点,那么就把信息放到这个儿子节点上. 注意,lca的 ...
- SPOJ 375 Query on a tree(树链剖分)
https://vjudge.net/problem/SPOJ-QTREE 题意: 给出一棵树,树上的每一条边都有权值,现在有查询和更改操作,如果是查询,则要输出u和v之间的最大权值. 思路: 树链剖 ...
- 【SPOJ Query on a tree 】 (树链剖分)
http://acm.hust.edu.cn/vjudge/problem/13013 题意: 有一棵N个节点的树(1<=N<=10000),N-1条边,边的编号为1~N-1,每条边有一个 ...
随机推荐
- Slickflow.NET 开源工作流引擎基础介绍(四) -- 多数据库支持实现
前言:引擎作为中间件集成到用户的项目里面去,针对用户的数据库类型,需要作出SQL部分的分别实现.引擎默认数据库为MS SQLSERVER,同时也支持ORACLE, MYSQL, KINGBASE等不同 ...
- SVN对unity3d项目版本进行管理的不方便问题,研究ing
unity3d项目版本控制遇到些问题,找了以下资料做参考,现在mark一下,以后慢慢解决,之后总结. Unity开启meta. meta:版本控制文件,在新加入项时,Unity3D会产生一个同名的.m ...
- MSSQL Server 导入/导出到远程服务器
1.打开本地企业管理器,先创建一个SQL Server注册来远程连接服务器端口SQL Server. 步骤如下图: 图1: 2.弹出窗口后输入内容."总是提示输入登陆名和密码"可选 ...
- BLK-MD-BC04-B蓝牙模块的资料
BLK-MD-BC04-B蓝牙模块的资料 蓝牙模块说明 蓝牙模块 波特率 波特率从1200到1382400,具体可以参考波特率列表. 电平接口 答:模块的接口是SPP电平,电压为3.3V. ...
- CSS常见的浏览器前缀
为了让浏览器识别某些专属属性,有时候需要在CSS属性前增加浏览器前缀 -ms-:Microsoft IE -moz-:Mozilla Firefox -o-:Opera Opera -webkit-: ...
- YSPASYS 中小型企业简单员工评价考核系统
背景:公司运营接近2年时间了,随着不断的有员工入职.离职,使用信息化管理员工各类信息是一件很有必要的事儿.诸如员工基本信息,内部公告,资产盘点,客户管理,工作周报,优秀员工评选,请假.外出.报销.采购 ...
- 关于jQuery中.attr()和.prop()的问题
话说写了几句代码在ie8上能正常运行,chrome和ff却不行,朋友说这就是RP啊,郁闷! 其实功能需求是这样的,两个radio:男和女,一个button:重置.启动页面默认选中男,在用户选择女之后又 ...
- (hdu)5423 Rikka with Tree (dfs)
题目链接:http://acm.split.hdu.edu.cn/showproblem.php?pid=5423 Problem Description As we know, Rikka is p ...
- Google Breakpad part 1 : Getting Started With Windows Client
准备 1.Python 2.Visual Studio 3.svn checkout http://google-breakpad.googlecode.com/svn/trunk/ source c ...
- [android网络有效性检测] NetworkMonitor代码造成内存泄漏
造成内存泄漏的log如下: E StrictMode: A resource was acquired at attached stack trace but never released. See ...