【BZOJ3514】Codechef MARCH14 GERALD07加强版

Description

N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数。

Input

第一行四个整数N、M、K、type,代表点数、边数、询问数以及询问是否加密。
接下来M行,代表图中的每条边。
接下来K行,每行两个整数L、R代表一组询问。对于type=0的测试点,读入的L和R即为询问的L、R;对于type=1的测试点,每组询问的L、R应为L xor lastans和R xor lastans。

Output

K行每行一个整数代表该组询问的联通块个数。

Sample Input

3 5 4 0
1 3
1 2
2 1
3 2
2 2
2 3
1 5
5 5
1 2

Sample Output

2
1
3
1

HINT

对于100%的数据,1≤N、M、K≤200,000。

题解:本题思路很神~

我们将边按编号一条一条地加到图中,如果当前边a,b所在的连通块已经连通,则我们找到这个连通块中编号最小的边,记录它的编号kick[i],并将它删去,然后将当前边加入到图中。这个可以用LCT很容易的实现。(套路:用LCT维护边权的方法,将边变成点,a-b连边视为a-c-b连边,然后图中只有从边变过来的点才有权值)

然后采用主席树,在i的主席树中将kick[i]删除,然后查询[l,r]时再r的主席树中查询[l,r]这段区间,就能得到区间中有多少树边了。

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn=200010;
int n,m,Q,typ,tot,ans;
int pa[maxn],pb[maxn],f[maxn],rt[maxn],sum[maxn];
struct LCT
{int ch[2],fa,rev,mn,val;
}t[maxn<<1];
struct sag
{int ls,rs,siz;
}s[maxn*40];
inline bool isr(int x) {return t[t[x].fa].ch[0]!=x&&t[t[x].fa].ch[1]!=x;}
inline void rever(int x)
{swap(t[x].ch[0],t[x].ch[1]),t[x].rev^=1;
}
inline void pushdown(int x)
{if(t[x].rev){if(t[x].ch[0])    rever(t[x].ch[0]);if(t[x].ch[1])    rever(t[x].ch[1]);t[x].rev=0;}
}
inline void pushup(int x)
{t[x].mn=min(t[x].val,min(t[t[x].ch[0]].mn,t[t[x].ch[1]].mn));
}
inline void rotate(int x)
{int y=t[x].fa,z=t[y].fa,d=(x==t[y].ch[1]);if(!isr(y)) t[z].ch[y==t[z].ch[1]]=x;t[x].fa=z,t[y].fa=x,t[y].ch[d]=t[x].ch[d^1];if(t[x].ch[d^1]) t[t[x].ch[d^1]].fa=y;t[x].ch[d^1]=y;pushup(y),pushup(x);
}
void updata(int x)
{if(!isr(x))    updata(t[x].fa);pushdown(x);
}
inline void splay(int x)
{updata(x);while(!isr(x)){int y=t[x].fa,z=t[y].fa;if(!isr(y)){if((x==t[y].ch[1])^(y==t[z].ch[1])) rotate(x);else  rotate(y);}rotate(x);}
}
inline void access(int x)
{for(int y=0;x;splay(x),t[x].ch[1]=y,pushup(x),y=x,x=t[x].fa);
}
inline void maker(int x)
{access(x),splay(x),rever(x);
}
inline void link(int a,int b)
{maker(a),t[a].fa=b;
}
inline void cut(int a,int b)
{maker(a),access(b),splay(b),t[a].fa=t[b].ch[0]=0,pushup(b);
}
void insert(int x,int &y,int l,int r,int a,int b)
{y=++tot,s[y].siz=s[x].siz+1;if(l==r)    return ;int mid=(l+r)>>1;if(a<=mid) s[y].rs=s[x].rs,insert(s[x].ls,s[y].ls,l,mid,a,b);else s[y].ls=s[x].ls,insert(s[x].rs,s[y].rs,mid+1,r,a,b);
}
int query(int x,int l,int r,int a,int b)
{if(!x||(a<=l&&r<=b))   return s[x].siz;int mid=(l+r)>>1;if(b<=mid) return query(s[x].ls,l,mid,a,b);if(a>mid)    return query(s[x].rs,mid+1,r,a,b);return query(s[x].ls,l,mid,a,b)+query(s[x].rs,mid+1,r,a,b);
}
int find(int x)
{return (f[x]==x)?x:(f[x]=find(f[x]));
}
inline int rd()
{int ret=0,f=1;   char gc=getchar();while(gc<'0'||gc>'9')  {if(gc=='-')    f=-f;  gc=getchar();}while(gc>='0'&&gc<='9')  ret=ret*10+gc-'0',gc=getchar();return ret*f;
}
int main()
{n=rd(),m=rd(),Q=rd(),typ=rd();int i,a,b,c;for(i=0;i<=n;i++) f[i]=i,t[i].val=t[i].mn=m+1;for(i=1;i<=m;i++)    t[i+n].val=t[i+n].mn=i;for(i=1;i<=m;i++){a=pa[i]=rd(),b=pb[i]=rd(),sum[i]=sum[i-1]+1;if(a==b)    sum[i]--,rt[i]=rt[i-1];else    if(find(a)==find(b)){maker(a),access(b),splay(b),c=t[b].mn;insert(rt[i-1],rt[i],1,m,c,1);cut(pa[c],c+n),cut(pb[c],c+n),link(a,i+n),link(b,i+n);}else f[f[a]]=f[b],link(a,i+n),link(b,i+n),rt[i]=rt[i-1];}for(i=1;i<=Q;i++){a=rd()^(ans*typ),b=rd()^(ans*typ);ans=n-(sum[b]-sum[a-1]-query(rt[b],1,m,a,b));printf("%d\n",ans);}return 0;
}//3 5 4 0 1 3 1 2 2 1 3 2 2 2 2 3 1 5 5 5 1 2 

转载于:https://www.cnblogs.com/CQzhangyu/p/7670107.html

【BZOJ3514】Codechef MARCH14 GERALD07加强版 LCT+主席树相关推荐

  1. BZOJ 3514 Codechef MARCH14 GERALD07 加强版 LCT+主席树

    题意: N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. 分析: 据说有dalao会离线做这题? 看到L和R就能想到主席树?dalao们太强了-- 如果我们给出n个点,m ...

  2. BZOJ3514 Codechef MARCH14 GERALD07加强版 LCT维护最大生成树 主席树

    题面 考虑没有询问,直接给你一个图问联通块怎么做. 并查集是吧. 现在想要动态地做,那么应该要用LCT. 考虑新加进来一条边,想要让它能够减少一个联通块的条件就是现在边的两个端点还没有联通. 如果联通 ...

  3. BZOJ3514:GERALD07加强版(LCT,主席树)

    Description N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. Input 第一行四个整数N.M.K.type,代表点数.边数.询问数以及询问是否加密. 接下来 ...

  4. bzoj3514: Codechef MARCH14 GERALD07加强版

    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3514 思路:这题思路很巧妙 首先每个连通块只要保留一棵生成树的边就可以保证连通了 把每条边的 ...

  5. 【洛谷P5385】须臾幻境/【BZOJ3514】Codechef MARCH14 GERALD07加强版【LCT】【主席树】

    题意:有nnn个点mmm条边,qqq次询问连接区间[L,R][L,R][L,R]中的边后的连通块个数.强制在线. n,m,q≤2×105n,m,q\leq 2\times10^5n,m,q≤2×105 ...

  6. 【BZOJ3514】Codechef MARCH14 GERALD07加强版,LCT+主席树

    Time:2016.08.06 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: 今天模拟题T3 结果是看都没看?? n,m<=1000 每次直接暴力并查集,O(n)判断 复杂度 ...

  7. 【bzoj3514】 Codechef MARCH14 GERALD07加强版

    http://www.lydsy.com/JudgeOnline/problem.php?id=3514 (题目链接) 题意 给出$n$个点$m$条边的无向图,询问保留图中编号在$[l,r]$的边的时 ...

  8. 2017.10.17 Codechef MARCH14 GERALD07加强版 失败总结

    以前做这个题简直是噩梦的难度 有个很神的做法就是 利用最简联通形式来统计联通块 把一个要求的区间写成一颗等价的树,,就有了统一的标准 然后考虑怎么构造这棵树,看每次加入的边,如果已经联通,则考虑把这个 ...

  9. BZOJ 3514 Codechef MARCH14 GERALD07加强版

    从CC抠的题 xyz大神直接用分块秒 虽然会MLE+TLE 时限被改成40s了,我觉得30s足够了吧-- 考虑从左至右加入每一条边,加入某条边成环的环那么这条边对答案就没有影响.那么只要环上标号最小的 ...

最新文章

  1. PHP basename() 函数
  2. OpenCV 【六】————youtu(图像)——旋转保存图片
  3. salt-master
  4. vue中使用 i18n 遇到的问题
  5. hibernate:无法级联插入
  6. python中的深拷贝_Python中的深拷贝和浅拷贝
  7. 基于JAVA+SpringMVC+Mybatis+MYSQL的酒店客房管理系统
  8. 客户端父进程提前死亡
  9. 两男子骑摩托车抢夺宴席礼金 警方:嫌疑人已被抓获
  10. ES6新语法之let关键字;有别于传统关键字var的使用
  11. 对于委托的理解 委托和事件
  12. Android 高通配置SUPL
  13. Android 点击按钮出现弹窗
  14. 3dmax最基础的建模教程
  15. ttest求pvalue_TTEST 在EXCEL计算出的结果是t还是p值
  16. DNA甲基化与组蛋白修饰之间的关系
  17. snappy格式解析
  18. 修改Linux下只读文件的权限
  19. linux版高德导航软件下载,【高德导航离线地图包下载】高德地图离线包 -ZOL软件下载...
  20. MarkDown 排版测试

热门文章

  1. 【原】Spark中Master源码分析(一)
  2. Java从入门到精通——数据库篇Mongo DB GridFS文件系统
  3. HDU 3397 线段树 双懒惰标记
  4. 解决IE6透明PNG图片的代码
  5. WinCE下监视设备插拔的参考代码
  6. 在.NET中excel导出方法汇总(收集)
  7. iOS开发之普通网络异步请求与文件下载方法
  8. 第三章 中间件,3.1 万亿级数据洪峰下的分布式消息引擎(作者:冯嘉、誓嘉、尘央、牟羽)...
  9. Simulated Annealing(模拟退火算法)
  10. 读c语言深度剖析 -- 单引号与双引号、逻辑运算符、位运算符、花括号