4229: 选择

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 67  Solved: 41

Description

现在,我想知道自己是否还有选择。
给定n个点m条边的无向图以及顺序发生的q个事件。
每个事件都属于下面两种之一:
1、删除某一条图上仍存在的边
2、询问是否存在两条边不相交的路径可以从点u出发到点v

Input

第一行三个整数n,m,q
接下来m行,每行两个整数u,v,表示u和v之间有一条边
接下来q行,每行一个大写字母o和2个整数u、v,依次表示按顺序发生的q个事件:
当o为’Z’时,表示删除一条u和v之间的边
当o为’P’时,表示询问是否存在两条边不相交的路径可以从点u出发到点v

Output

对于每组询问,如果存在,输出Yes,否则输出No

Sample 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 6

Sample Output

Yes
Yes
No
No

HINT

对于全部数据,max(n,m,q)<=100000

Source

【分析】

  我的做法跟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: 选择 (线段树+树链剖分)的更多相关文章

  1. 线段树&数链剖分

    傻逼线段树,傻逼数剖 线段树 定义: 线段树是一种二叉搜索树,与区间树相似,它将一个区间划分成一些单元区间,每个单元区间对应线段树中的一个叶结点. 使用线段树可以快速的查找某一个节点在若干条线段中出现 ...

  2. UOJ#30/Codeforces 487E Tourists 点双连通分量,Tarjan,圆方树,树链剖分,线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ30.html 题目传送门 - UOJ#30 题意 uoj写的很简洁.清晰,这里就不抄一遍了. 题解 首先建 ...

  3. BZOJ1758[Wc2010]重建计划——分数规划+长链剖分+线段树+二分答案+树形DP

    题目描述 输入 第一行包含一个正整数N,表示X国的城市个数. 第二行包含两个正整数L和U,表示政策要求的第一期重建方案中修建道路数的上下限 接下来的N-1行描述重建小组的原有方案,每行三个正整数Ai, ...

  4. [LOJ3014][JOI 2019 Final]独特的城市——树的直径+长链剖分

    题目链接: [JOI 2019 Final]独特的城市 对于每个点,它的答案最大就是与它距离最远的点的距离. 而如果与它距离为$x$的点有大于等于两个,那么与它距离小于等于$x$的点都不会被计入答案. ...

  5. CF487E Tourists 圆方树、树链剖分

    传送门 注意到我们需要求的是两点之间所有简单路径中最小值的最小值,那么对于一个点双联通分量来说,如果要经过它,则一定会经过这个点双联通分量里权值最小的点 注意:这里不能缩边双联通分量,样例\(2\)就 ...

  6. BZOJ 1758 / Luogu P4292 [WC2010]重建计划 (分数规划(二分/迭代) + 长链剖分/点分治)

    题意 自己看. 分析 求这个平均值的最大值就是分数规划,二分一下就变成了求一条长度在[L,R]内路径的权值和最大.有淀粉质的做法但是我没写,感觉常数会很大.这道题可以用长链剖分做. 先对树长链剖分. ...

  7. 2019.01.08 codeforces 1009F. Dominant Indices(长链剖分)

    传送门 长链剖分模板题. 题意:给出一棵树,设fi,jf_{i,j}fi,j​表示iii的子树中距离点iii距离为jjj的点的个数,现在对于每个点iii要求出使得fif_ifi​取得最大值的那个jjj ...

  8. 【LOJ】#3014. 「JOI 2019 Final」独特的城市(长链剖分)

    LOJ#3014. 「JOI 2019 Final」独特的城市(长链剖分) 显然我们画一条直径,容易发现被统计的只可能是直径某个距离较远的端点到这个点的路径上的值 用一个栈统计可以被统计的点,然后我们 ...

  9. BZOJ.1036 [ZJOI2008]树的统计Count ( 点权树链剖分 线段树维护和与最值)

    BZOJ.1036 [ZJOI2008]树的统计Count (树链剖分 线段树维护和与最值) 题意分析 (题目图片来自于 这里) 第一道树链剖分的题目,谈一下自己的理解. 树链剖分能解决的问题是,题目 ...

  10. BZOJ 3672: [Noi2014]购票( 树链剖分 + 线段树 + 凸包 )

    s弄成前缀和(到根), dp(i) = min(dp(j) + (s(i)-s(j))*p(i)+q(i)). 链的情况大家都会做...就是用栈维护个下凸包, 插入时暴力弹栈, 查询时就在凸包上二分/ ...

随机推荐

  1. idea自动识别get set方法

  2. python学习笔记(十五)之集合

    集合:对应数学中的集合类型.集合中的元素是唯一,且无序的. 创建集合 方法一:使用{},注意python会自动删除重复元素 >>> number = {1,2,3,4,3,2,1} ...

  3. python-num18 - django进阶一

    一.深入django的路由系统 下面为django的请求生命周期 下面来看下整个生命周期中的路由系统: 在Django的urls中我们可以根据一个URL对应一个函数名来定义路由规则如下: " ...

  4. css_input[checked]复选框去掉默认样式并添加新样式

    效果对比: “\2713”实体符号√ :如有兴趣查看详细实体符号请点这里 代码实现: <!DOCTYPE html> <html> <head> <meta ...

  5. Python3中字符串的编码与解码以及编码之间转换(decode、encode)

    一.编码 二.编码与解码 Python3中对py文件的默认编码是urf-8.但是字符串的编码是Unicode. 由于Unicode采用32位4个字节来表示一个字符,存储和传输太浪费资源,所以传输和存储 ...

  6. HDU 3018 Ant Trip (并查集求连通块数+欧拉回路)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3018 题目大意:有n个点,m条边,人们希望走完所有的路,且每条道路只能走一遍.至少要将人们分成几组. ...

  7. XSS与CSRF两种跨站攻击总结

    在那个年代,大家一般用拼接字符串的方式来构造动态 SQL 语句创建应用,于是 SQL 注入成了很流行的攻击方式.在这个年代, 参数化查询 [1] 已经成了普遍用法,我们已经离 SQL 注入很远了.但是 ...

  8. Linux下突然不识别无线网卡

    昨天还能用wifi的Linux,今天进去后发现没有了wifi的图标,ifconfig也不显示无线网卡.怎么办? 出现这种情况,肯定是上次关机之前做了一些操作导致的.我遇到过的一个情况是:Fedora2 ...

  9. 小技巧:tar命令打包目录时,排除文件和目录的命令

    今天不巧要用上,百度. tar zcvf fd.tar.gz pardir --exclude=pardir/file1 --exclude=pardir/dir1

  10. day5模块

    模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要多个函数才 ...