BZOJ 1969 树链剖分+Tarjan缩点
发现自己Tarjan的板子有错误.发现可以用Map直接删去边,Get.
听说std是双连通、LCA、并查集、离线思想、用BIT维护dfs序和并查集维护LCA的动态缩点的好题
#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <set>
#include <stack>
#define mp make_pair
#define pa pair<int,int>
#define pb push_back
#define fi first
#define se second
using namespace std;
inline void Get_Int(int &x)
{
x=; char ch=getchar(); int f=;
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();} x*=f;
}
inline void Put_Int(int x)
{
char ch[]; int top=;
if (x==) ch[++top]='';
while (x) ch[++top]=x%+'',x/=;
while (top) putchar(ch[top--]); putchar('\n');
}
//===================================================
const int Maxm=;
const int Maxn=;
const int Maxop=;
struct EDGE{int to,next;}edge[Maxm];
struct OP{int type,u,v;}Op[Maxop];
int head[Maxn],siz[Maxn],father[Maxn],top[Maxn],dep[Maxn],num[Maxn],sum[Maxn<<],clr[Maxn<<];
int Belong[Maxn],Low[Maxn],Dfn[Maxn],Ans[Maxn];
int Stack[Maxn];
int stamp,Stamp,cnt,scc,apex,Q,n,m,u,v;
bool vis[Maxn];
map<pa,bool> Edge;
vector<pa> V;
set <pa> S;
inline void Add(int u,int v)
{edge[cnt].to=v;edge[cnt].next=head[u];head[u]=cnt++;}
inline int Max(int x,int y) {return x>y?x:y;}
inline int Min(int x,int y) {return x>y?y:x;}
inline void Build_G()
{
map<pa,bool>::iterator it;
for (it=Edge.begin();it!=Edge.end();it++)
if (it->se)
Add(it->fi.fi,it->fi.se);
}
inline void Clear_G()
{
map<pa,bool>::iterator it;
for (it=Edge.begin();it!=Edge.end();it++)
if (it->se) it->se=false;
}
//================================================= void Dfs1(int u)
{
vis[u]=true; siz[u]=;
for (int i=head[u];i!=-;i=edge[i].next)
if (!vis[edge[i].to])
{
father[edge[i].to]=u;
dep[edge[i].to]=dep[u]+;
Dfs1(edge[i].to);
siz[u]+=siz[edge[i].to];
}
}
void Dfs2(int u,int chain)
{
num[u]=++stamp; top[u]=chain; vis[u]=true; int k=;
for (int i=head[u];i!=-;i=edge[i].next)
if (!vis[edge[i].to] && (siz[edge[i].to]>siz[k] || k==)) k=edge[i].to;
if (k==) return;
Dfs2(k,chain);
for (int i=head[u];i!=-;i=edge[i].next)
if (!vis[edge[i].to] && edge[i].to!=k) Dfs2(edge[i].to,edge[i].to);
} inline int Lca(int u,int v)
{
while (true)
{
if (top[u]==top[v]) return dep[u]>dep[v]?v:u;
if (dep[top[u]]>dep[top[v]]) u=father[top[u]]; else v=father[top[v]];
}
}
//================================================== inline void push_up(int o) {sum[o]=sum[o<<]+sum[o<<|];}
inline void Clr(int o) {clr[o]=; sum[o]=;}
inline void push_down(int o) {if (clr[o]) Clr(o<<),Clr(o<<|); clr[o]=;}
void Modify(int o,int l,int r,int p,int q)
{
if (l==p && r==q)
{
sum[o]=;
clr[o]=;
return;
}
push_down(o);
int mid=(l+r)>>;
if (q<=mid) Modify(o<<,l,mid,p,q);
if (p>=mid+) Modify(o<<|,mid+,r,p,q);
if (p<=mid && q>=mid+) Modify(o<<,l,mid,p,mid),Modify(o<<|,mid+,r,mid+,q);
push_up(o);
}
int Query(int o,int l,int r,int p,int q)
{
if (l==p && r==q) return sum[o];
push_down(o);
int mid=(l+r)>>;
if (q<=mid) return Query(o<<,l,mid,p,q);
if (p>=mid+) return Query(o<<|,mid+,r,p,q);
if (p<=mid && q>=mid+) return Query(o<<,l,mid,p,mid)+Query(o<<|,mid+,r,mid+,q);
}
void Build(int o,int l,int r)
{
if (l==r)
{
sum[o]=;
return;
}
int mid=(l+r)>>;
Build(o<<,l,mid),Build(o<<|,mid+,r);
push_up(o);
} //=================================================
void Tree_Modify(int u,int v)
{
while (top[u]!=top[v])
{
Modify(,,scc,num[top[u]],num[u]);
u=father[top[u]];
}
Modify(,,scc,num[v],num[u]);
}
int Tree_Query(int u,int v)
{
int ret=; while (top[u]!=top[v])
{
ret+=Query(,,scc,num[top[u]],num[u]);
u=father[top[u]];
}
ret+=Query(,,scc,num[v],num[u]);
return ret;
}
//=================================================
void Tarjan(int u,int fa)
{
Low[u]=Dfn[u]=++Stamp; Stack[++apex]=u;
for(int i=head[u];i!=-;i=edge[i].next)
if (edge[i].to!=fa)
{
int v=edge[i].to;
if(!Dfn[v])
{
Tarjan(v,u);
Low[u]=Min(Low[u],Low[v]);
if(Low[v]>Dfn[u])
{
scc++;
while(true) {int x=Stack[apex--]; Belong[x]=scc; if(x==v)break;}
}
}
else Low[u]=Min(Low[u],Dfn[v]);
}
if(fa<)
{
scc++;
while(true){int x=Stack[apex--]; Belong[x]=scc; if(x==u)break;}
}
}
//================================================= int main()
{
//freopen("c.in","r",stdin);
Get_Int(n),Get_Int(m);
for (int i=;i<=m;i++)
Get_Int(u),Get_Int(v),Edge[mp(u,v)]=true,Edge[mp(v,u)]=true; for (Q=;;Q++)
{
Get_Int(Op[Q].type); if (Op[Q].type==-) break;
Get_Int(Op[Q].u),Get_Int(Op[Q].v);
if (Op[Q].type==) Edge[mp(Op[Q].u,Op[Q].v)]=false,Edge[mp(Op[Q].v,Op[Q].u)]=false;
}
Q--;
stamp=Stamp=cnt=;
memset(head,-,sizeof(head));
memset(vis,false,sizeof(vis));
memset(Low,,sizeof(Low));
memset(Dfn,,sizeof(Dfn)); Build_G();
Tarjan(,-);
Clear_G();
for (int i=;i<=n;i++)
for (int j=head[i];j!=-;j=edge[j].next)
if (Belong[i]!=Belong[edge[j].to])
{
if (S.count(mp(Belong[i],Belong[edge[j].to]))==) continue;
S.insert(mp(Belong[i],Belong[edge[j].to]));
S.insert(mp(Belong[edge[j].to],Belong[i]));
V.pb(mp(Belong[i],Belong[edge[j].to]));
V.pb(mp(Belong[edge[j].to],Belong[i]));
} memset(head,-,sizeof(head));cnt=;
for (int i=;i<V.size();i++) Add(V[i].fi,V[i].se);
father[]=;dep[]=;
memset(vis,false,sizeof(vis)),Dfs1();
memset(vis,false,sizeof(vis)),Dfs2(,);
Build(,,scc);
for (int i=Q;i>=;i--)
{
int p=Belong[Op[i].u],q=Belong[Op[i].v];
if (Op[i].type==)
{
if (p==q) continue;
int t=Lca(p,q);
if (t==p)
{
int k=;
for (int j=head[t];j!=-;j=edge[j].next)
if (Lca(edge[j].to,q)==edge[j].to && father[t]!=edge[j].to) {k=edge[j].to; break;} Tree_Modify(q,k);
continue;
} if (t==q)
{
int k=;
for (int j=head[t];j!=-;j=edge[j].next)
if (Lca(edge[j].to,p)==edge[j].to && father[t]!=edge[j].to) {k=edge[j].to; break;}
Tree_Modify(p,k);
continue;
}
int r,s;
for (int j=head[t];j!=-;j=edge[j].next)
if (Lca(edge[j].to,p)==edge[j].to && father[t]!=edge[j].to) {r=edge[j].to; break;}
for (int j=head[t];j!=-;j=edge[j].next)
if (Lca(edge[j].to,q)==edge[j].to && father[t]!=edge[j].to) {s=edge[j].to; break;}
Tree_Modify(p,r),Tree_Modify(q,s);
} else
if (Op[i].type==)
{
if (p==q) {Ans[i]=; continue;}
int t=Lca(p,q);
if (t==p)
{
int k=;
for (int j=head[t];j!=-;j=edge[j].next)
if (Lca(edge[j].to,q)==edge[j].to && father[t]!=edge[j].to) {k=edge[j].to; break;}
Ans[i]=Tree_Query(q,k);
continue;
}
if (t==q)
{
int k=;
for (int j=head[t];j!=-;j=edge[j].next)
if (Lca(edge[j].to,p)==edge[j].to && father[t]!=edge[j].to) {k=edge[j].to; break;}
Ans[i]=Tree_Query(p,k);
continue;
} int r,s;
for (int j=head[t];j!=-;j=edge[j].next)
if (Lca(edge[j].to,p)==edge[j].to && father[t]!=edge[j].to) {r=edge[j].to; break;}
for (int j=head[t];j!=-;j=edge[j].next)
if (Lca(edge[j].to,q)==edge[j].to && father[t]!=edge[j].to) {s=edge[j].to; break;}
Ans[i]=Tree_Query(p,r)+Tree_Query(q,s);
}
}
for (int i=;i<=Q;i++)
if (Op[i].type==) Put_Int(Ans[i]);
return ;
}
傻逼树剖280+系列
BZOJ 1969 树链剖分+Tarjan缩点的更多相关文章
- BZOJ_4326_[NOIP2015]_运输计划_(二分+LCA_树链剖分/Tarjan+差分)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=4326 给出一棵带有边权的树,以及一系列任务,任务是从树上的u点走到v点,代价为u到v路径上的权 ...
- BZOJ 4326 树链剖分+二分+差分+记忆化
去年NOIP的时候我还不会树链剖分! 还是被UOJ 的数据卡了一组. 差分的思想还是很神啊! #include <iostream> #include <cstring> #i ...
- BZOJ 1036 && 树链剖分
还是太弱啊..各种数据结构只听过名字却没有一点概念..树链剖分也在这个范畴..今天来进一步深化一下教育改革推进全民素质提高. 性质 忘了在哪里看到的一篇blog有一句话讲得非常好,树链剖分不是一种数据 ...
- bzoj 3083 树链剖分
首先我们先将树提出一个根变成有根树,那么我们可以通过树链剖分来实现对于子树的最小值求解,那么按照当前的根和询问的点的相对位置关系我们可以将询问变成某个子树和或者除去某颗子树之后其余的和,前者直接询问区 ...
- bzoj 2243 树链剖分
2013-11-19 16:21 原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=2243 树链剖分,用线段树记录该区间的颜色段数,左右端点颜 ...
- bzoj 4196 树链剖分 模板
[Noi2015]软件包管理器 Time Limit: 10 Sec Memory Limit: 512 MBSubmit: 2135 Solved: 1232[Submit][Status][D ...
- BZOJ 4811 树链剖分+线段树
思路: 感觉这题也可神了.. (还是我太弱) 首先发现每一位不会互相影响,可以把每一位分开考虑,然后用树链剖分或者LCT维护这个树 修改直接修改,询问的时候算出来每一位填0,1经过这条链的变换之后得到 ...
- BZOJ 4034 树链剖分
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4034 题意:中文题面 思路:树链剖分入门题. 剖分后就是一个简单的区间更新和区间求和问题. ...
- BZOJ 2286 树链剖分+DFS序+虚树+树形DP
第一次学习虚树,就是把无关的点去掉.S里维护一条链即可. #include <iostream> #include <cstring> #include <cstdio& ...
随机推荐
- LA 3523 圆桌骑士
题目链接:http://vjudge.net/contest/141787#problem/A http://poj.org/problem?id=2942 此题很经典 知识点:DFS染色,点-双连通 ...
- 关于Extjs MVC模式上传文件的简单方式
Extjs新手研究上传文件的事情估计是件很头痛的问题,毕竟,我就在头痛.最近两天一直在忙文件上传问题,终于小有收获. 用的是Extjs+MVC3.0+EF开发,语言为C#.前台window代码显示列内 ...
- angular之控制器(0)
一.控制器的含义 在angularJS中,controlle是一个javascript函数/类,用于操作作用域中,各个对象的初始状态以及相应的行为 二.控制器的作用 1. 控制 AngularJS 应 ...
- EasyUI中动态生成标签页
这是最近学到的内容,当时是有思路但是不知道怎么获取当前的点击对象,就没有实现功能,通过更深入的学习,我知道了不仅仅是Java,Oracle中有一个this,同样的EasyUI中也存在一个this,来获 ...
- Java与JavaScript的区别
(1)执行方式不同 java:是编译语言,需要先编译再执行 JavaScript:无需编译,直接执行 (2)数据类型不同 java:强数据类型语言 JavaScript:弱数据类型语言 (3)运行位置 ...
- 配置eclipse集成开发环境_编译_调试
1. 因为eclipse是基于Java运行,所以在运行Eclipse之前,需要安装Java SE,对于Java SE,需要Java SE6 JRE系列的版本,可以在这个位置下载: Java SE 6只 ...
- Scrum Meeting 3-20151203
任务安排 姓名 今日任务 明日任务 困难 董元财 请假(明天是编译截至最后一天) 学习上拉加入新的listview 无 胡亚坤 请假(明天是编译截至最后一天) 设计优化聊天页面 无 刘猛 请假(明天是 ...
- IOS开发之WIFI及IP相关
获取手机设备的IP信息: #import <ifaddrs.h> #import <arpa/inet.h> // Get IP Address - (NSString *)g ...
- Deep Learning 6_深度学习UFLDL教程:Softmax Regression_Exercise(斯坦福大学深度学习教程)
前言 练习内容:Exercise:Softmax Regression.完成MNIST手写数字数据库中手写数字的识别,即:用6万个已标注数据(即:6万张28*28的图像块(patches)),作训练数 ...
- havok之内存管理
[现象记录] 1.往world和rb里都各自加入一个entityListener,当这个rb被remove掉之后, 会首先调用world里的listener的removecallback, 再调用rb ...