【BZOJ 4229】 4229: 选择 (线段树+树链剖分)
4229: 选择
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 67 Solved: 41Description
现在,我想知道自己是否还有选择。给定n个点m条边的无向图以及顺序发生的q个事件。每个事件都属于下面两种之一:1、删除某一条图上仍存在的边2、询问是否存在两条边不相交的路径可以从点u出发到点vInput
第一行三个整数n,m,q接下来m行,每行两个整数u,v,表示u和v之间有一条边接下来q行,每行一个大写字母o和2个整数u、v,依次表示按顺序发生的q个事件:当o为’Z’时,表示删除一条u和v之间的边当o为’P’时,表示询问是否存在两条边不相交的路径可以从点u出发到点vOutput
对于每组询问,如果存在,输出Yes,否则输出NoSample Input
7 8 7
1 2
1 3
1 4
2 3
3 4
3 7
7 4
5 6
Z 1 4
P 1 3
P 2 4
Z 1 3
P 1 3
Z 6 5
P 5 6Sample Output
Yes
Yes
No
NoHINT
对于全部数据,max(n,m,q)<=100000Source
【分析】
我的做法跟BZOJ 1969大致一样【我改了改代码交的。。
这题没说删完的图联通,所以最后还要处理一下。。
然后每次询问x到y的关键边数量是否为0就好了。
【详细做法见BZOJ 1969
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define Maxn 100010
#define Maxm 100010 struct node
{
int x,y,next;
int bj,id;
}t[Maxn*],tt[Maxm*];
int first[Maxn],len; void ins(int x,int y)
{
// printf("%d -> %d\n",x,y);
t[++len].x=x;t[len].y=y;
t[len].next=first[x];first[x]=len;
} struct nnode
{
int l,r,lc,rc,sm;
}tr[Maxn*]; void upd(int x)
{
if(tr[x].l==tr[x].r||tr[x].sm!=) return;
int lc=tr[x].lc,rc=tr[x].rc;
tr[lc].sm=tr[rc].sm=;
} int tot;
int build(int l,int r)
{
int x=++tot;
tr[x].l=l;tr[x].r=r;
if(l!=r)
{
int mid=(l+r)>>;
tr[x].lc=build(l,mid);
tr[x].rc=build(mid+,r);
}
else tr[x].lc=tr[x].rc=;
tr[x].sm=r-l+;
return x;
} void change(int x,int l,int r)
{
if(tr[x].l==l&&tr[x].r==r)
{
tr[x].sm=;
return;
}
upd(x);
int mid=(tr[x].l+tr[x].r)>>,lc=tr[x].lc,rc=tr[x].rc;
if(r<=mid) change(lc,l,r);
else if(l>mid) change(rc,l,r);
else
{
change(lc,l,mid);
change(rc,mid+,r);
}
tr[x].sm=tr[lc].sm+tr[rc].sm;
} int query(int x,int l,int r)
{
if(tr[x].sm==) return ;
if(tr[x].l==l&&tr[x].r==r) return tr[x].sm;
upd(x);
int mid=(tr[x].l+tr[x].r)>>,lc=tr[x].lc,rc=tr[x].rc;
if(r<=mid) return query(lc,l,r);
else if(l>mid) return query(rc,l,r);
else return query(lc,l,mid)+query(rc,mid+,r);
} int tp[Maxn],sum[Maxn],son[Maxn],dfn[Maxn],dep[Maxn];
int ff[Maxn];
int cnt;
void dfs(int x,int f)
{
son[x]=;sum[x]=;dep[x]=dep[f]+;
ff[x]=f;
for(int i=first[x];i;i=t[i].next) if(t[i].y!=f)
{
int y=t[i].y;
dfs(y,x);
sum[x]+=sum[y];
if(son[x]==||sum[son[x]]<sum[y]) son[x]=y;
}
} void dfs2(int x,int tpp)
{
dfn[x]=++cnt;tp[x]=tpp;
if(son[x]) dfs2(son[x],tpp);
for(int i=first[x];i;i=t[i].next) if(t[i].y!=ff[x]&&t[i].y!=son[x])
{
int y=t[i].y;
dfs2(y,y);
}
} void fchange(int x,int y)
{
while(tp[x]!=tp[y])
{
if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
change(,dfn[tp[x]],dfn[x]);
x=ff[tp[x]];
}
if(dep[x]<dep[y]) swap(x,y);
if(x!=y) change(,dfn[y]+,dfn[x]);
} int fquery(int x,int y)
{
int ans=;
while(tp[x]!=tp[y])
{
if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
ans+=query(,dfn[tp[x]],dfn[x]);
x=ff[tp[x]];
}
if(dep[x]<dep[y]) swap(x,y);
if(x!=y)
{
// if(dfn[y]+1>dfn[x]) while(1);
ans+=query(,dfn[y]+,dfn[x]);
}
return ans;
} int fa[Maxn];
int ffa(int x)
{
if(fa[x]!=x) fa[x]=ffa(fa[x]);
return fa[x];
} bool cmp(node x,node y)
{
if(x.x==y.x&&x.y==y.y) return x.bj<y.bj;
return (x.x==y.x)?(x.y<y.y):(x.x<y.x);
}
bool cmp2(node x,node y) {return x.id<y.id;} int ans[Maxn]; char s[]; void solve()
{
int n,m,q;
scanf("%d%d%d",&n,&m,&q);
int ll=;
for(int i=;i<=m;i++)
{
int x,y;
ll++;
scanf("%d%d",&tt[ll].x,&tt[ll].y);
if(tt[ll].x>tt[ll].y) swap(tt[ll].x,tt[ll].y);
tt[ll].bj=;//cha ru
}
int ct=;
while(q--)
{
scanf("%s",s);
ll++;
scanf("%d%d",&tt[ll].x,&tt[ll].y);
if(tt[ll].x>tt[ll].y) swap(tt[ll].x,tt[ll].y);
if(s[]=='Z') tt[ll].bj=-;//shan chu
else tt[ll].bj=;//xun wen
tt[ll].id=++ct;
}
sort(tt+,tt++ll,cmp);
for(int i=;i<=n;i++) fa[i]=i;
ct++;
int pp=;
for(int i=;i<=ll;i++)
{
if(tt[i].bj==) continue;
if(tt[i].bj==)
{
if(pp==||tt[i].x!=tt[pp].x||tt[i].y!=tt[pp].y)
{
if(ffa(tt[i].x)==ffa(tt[i].y))
{
tt[i].bj=-;
tt[i].id=ct;
}
else
{
ins(tt[i].x,tt[i].y);
ins(tt[i].y,tt[i].x);
fa[ffa(tt[i].x)]=tt[i].y;
}
}
}
pp=i;
}
sort(tt+,tt++ll,cmp2);
for(int i=ll;i>=;i--) if(tt[i].bj==-)
{
if(ffa(tt[i].x)!=ffa(tt[i].y))
{
ins(tt[i].x,tt[i].y);
ins(tt[i].y,tt[i].x);
fa[ffa(tt[i].x)]=tt[i].y;
tt[i].bj=;
}
}
dep[]=;cnt=;
for(int i=;i<=n;i++) if(ffa(i)==i)
{
dfs(i,);
dfs2(i,i);
}
build(,n); ans[]=;
for(int i=ll;i>=;i--)
{
if(tt[i].bj==) continue;
if(tt[i].bj==-)
{
fchange(tt[i].x,tt[i].y);
}
else
{
if(ffa(tt[i].x)!=ffa(tt[i].y)) ans[++ans[]]=-;
else ans[++ans[]]=fquery(tt[i].x,tt[i].y);
}
}
for(int i=ans[];i>=;i--)
{
if(ans[i]==) printf("Yes\n");
else printf("No\n");
}
} int main()
{
solve();
return ;
}
【是不是打的有点丑
2017-03-27 10:33:13
【BZOJ 4229】 4229: 选择 (线段树+树链剖分)的更多相关文章
- 线段树&数链剖分
傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...
- UOJ#30/Codeforces 487E Tourists 点双连通分量,Tarjan,圆方树,树链剖分,线段树
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ30.html 题目传送门 - UOJ#30 题意 uoj写的很简洁.清晰,这里就不抄一遍了. 题解 首先建 ...
- BZOJ1758[Wc2010]重建计划——分数规划+长链剖分+线段树+二分答案+树形DP
题目描述 输入 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai, ...
- [LOJ3014][JOI 2019 Final]独特的城市——树的直径+长链剖分
题目链接: [JOI 2019 Final]独特的城市 对于每个点,它的答案最大就是与它距离最远的点的距离. 而如果与它距离为$x$的点有大于等于两个,那么与它距离小于等于$x$的点都不会被计入答案. ...
- CF487E Tourists 圆方树、树链剖分
传送门 注意到我们需要求的是两点之间所有简单路径中最小值的最小值,那么对于一个点双联通分量来说,如果要经过它,则一定会经过这个点双联通分量里权值最小的点 注意:这里不能缩边双联通分量,样例\(2\)就 ...
- BZOJ 1758 / Luogu P4292 [WC2010]重建计划 (分数规划(二分/迭代) + 长链剖分/点分治)
题意 自己看. 分析 求这个平均值的最大值就是分数规划,二分一下就变成了求一条长度在[L,R]内路径的权值和最大.有淀粉质的做法但是我没写,感觉常数会很大.这道题可以用长链剖分做. 先对树长链剖分. ...
- 2019.01.08 codeforces 1009F. Dominant Indices(长链剖分)
传送门 长链剖分模板题. 题意:给出一棵树,设fi,jf_{i,j}fi,j表示iii的子树中距离点iii距离为jjj的点的个数,现在对于每个点iii要求出使得fif_ifi取得最大值的那个jjj ...
- 【LOJ】#3014. 「JOI 2019 Final」独特的城市(长链剖分)
LOJ#3014. 「JOI 2019 Final」独特的城市(长链剖分) 显然我们画一条直径,容易发现被统计的只可能是直径某个距离较远的端点到这个点的路径上的值 用一个栈统计可以被统计的点,然后我们 ...
- BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)
BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...
- BZOJ 3672: [Noi2014]购票( 树链剖分 + 线段树 + 凸包 )
s弄成前缀和(到根), dp(i) = min(dp(j) + (s(i)-s(j))*p(i)+q(i)). 链的情况大家都会做...就是用栈维护个下凸包, 插入时暴力弹栈, 查询时就在凸包上二分/ ...
随机推荐
- GridControl详解(六)样式设置
表格样式:全局设置 例子: 例子: 列样式:只作用于当前的列 通用样式:外观设定 注意:样式设定都是相同的,Appearance前缀.
- 客户端哈希加密(Javascript哈希加密,附源码)
摘要 我们很难想象用户在什么样的网络环境使用我们开发的应用,如果用户所处的网络环境不是一个可信任的环境,那么用户的账户安全就可能有威胁,比如用户登陆时提交的账号密码被网络嗅探器窃取:客户端加密数据能有 ...
- [linux]安装code::blocks
1.安装基本编译环境 $sudo apt-get install build-essential $sudo apt-get install gdb 2.安装codeblock $sudo apt-g ...
- 大图片上传(ImageIO,注意有的图片不能上传时因为他是tiff格式)
一下是必要的: 1.enctype="multipart/form-data" 2. //不要使用myeclipse自动生成的get.set方法(struts2中的用法) publ ...
- 记一次powershell反混淆(2)
样本地址 https://www.hybrid-analysis.com/sample/4b4b8b13c264c8f7d7034060e0e4818a573bebc576a94d7b13b4c174 ...
- xss自动化攻击
所需工具 [1.xssValidator] [2.phantomjs] [3.xss.js] /** * This is a basic phantomJS script that will be u ...
- 64_n3
nodejs-yamlish-0.0.5-9.fc26.noarch.rpm 11-Feb-2017 16:48 11966 nodejs-yargs-3.2.1-6.fc26.noarch.rpm ...
- 大数据系列之Flume+kafka 整合
相关文章: 大数据系列之Kafka安装 大数据系列之Flume--几种不同的Sources 大数据系列之Flume+HDFS 关于Flume 的 一些核心概念: 组件名称 功能介绍 Agent ...
- webstrom 使用git
1.首先进入码云创建项目 2.创建成功,复制https地址,打开webstrom,选择git,填入https的地址 3.下载完成,打开项目,新建一个测试测HTML文件,点击右键,选择git,再选择ad ...
- 浅谈Java中的hashcode方法(转)
原文链接:http://www.cnblogs.com/dolphin0520/p/3681042.html 浅谈Java中的hashcode方法 哈希表这个数据结构想必大多数人都不陌生,而且在很多地 ...