BZOJ 3514 Codechef MARCH14 GERALD07加强版 Link-Cut-Tree+划分树
题目大意:
给定n个点m条边的无向图。求问当图中仅仅有【编号在[l,r]区间内】的边存在时图中的联通块个数 强制在线
注意联通块是指联通了就是同一块,不是Tarjan求的那种块
看到这题的那一刻我就想小便有木有0.0 这尼玛怎么做?可持久化并查集? 暴力? 分块乱搞? 。。。
后来看了HZWER大神的博客才知道这样的巧妙的算法0.0 太强大了
直接复制wulala的题解 讲得非常清楚 不累述了
wulala
葱娘说这是一个非常巧妙的题。。
有一个比較猎奇的做法:首先把边依次加到图中,若当前这条边与图中的边形成了环,那么把这个环中最早加进来的边弹出去
并将每条边把哪条边弹了出去记录下来:ntr[i] = j,特别地,要是没有弹出边,ntr[i] = 0;
这个显然是能够用LCT来弄的对吧。
然后对于每一个询问,我们的答案就是对l~r中ntr小于l的边求和,并用n减去这个值
正确性能够YY一下:
假设一条边的ntr >= l,那么显然他能够与从l ~ r中的边形成环,那么它对答案没有贡献
反之假设一条边的ntr < l那么它与从l ~ r中的边是不能形成环的。那么他对答案的贡献为-1
对于查询从l ~ r中有多少边的ntr小于l,我反正是用的函数式线段树
这个真是太强大了0.0 假设这条边踢掉的最早的边也在[l,r]区间内 那么增加这条边一定对图的连通性没有影响 否则就会连接两个联通块 导致ans--
至于求l~r中有多少边的ntr小于l我用的是划分树 蒟蒻不会写主席树肿莫破。。
。
ntr。寝取り,果然是个够劲的名字。
。
。 于是为了保持这样的美好的意境我也牺牲了划分树中的a数组改成了ntr。。
。
把这个美好的意境传承下去吧。。
。
另外这题有自环 自环的话相当于自己ntr自己 直接记录ntr之后就返回好了
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 200200
#define INF 2147483647
using namespace std;
struct edges{
int x,y;
}e[M];
struct abcd{
abcd *fa,*ls,*rs;
int num,minnum;
bool rev_mark;
abcd(int x);
void Reverse();
void Push_Up();
void Push_Down();
}*null=new abcd(INF),*tree[M<<1];
abcd :: abcd(int x)
{
fa=ls=rs=null;
num=minnum=x;
rev_mark=0;
}
void abcd :: Reverse()
{
rev_mark^=1;
swap(ls,rs);
}
void abcd :: Push_Up()
{
minnum=min(ls->minnum,rs->minnum);
minnum=min(minnum,num);
}
void abcd :: Push_Down()
{
if(fa->ls==this||fa->rs==this)
fa->Push_Down();
if(rev_mark)
{
ls->Reverse();
rs->Reverse();
rev_mark=0;
}
}
void Zig(abcd *x)
{
abcd *y=x->fa;
y->ls=x->rs;
x->rs->fa=y;
x->rs=y;
x->fa=y->fa;
if(y==y->fa->ls)
y->fa->ls=x;
else if(y==y->fa->rs)
y->fa->rs=x;
y->fa=x;
y->Push_Up();
}
void Zag(abcd *x)
{
abcd *y=x->fa;
y->rs=x->ls;
x->ls->fa=y;
x->ls=y;
x->fa=y->fa;
if(y==y->fa->ls)
y->fa->ls=x;
else if(y==y->fa->rs)
y->fa->rs=x;
y->fa=x;
y->Push_Up();
}
void Splay(abcd *x)
{
x->Push_Down();
while(x->fa->ls==x||x->fa->rs==x)
{
abcd *y=x->fa,*z=y->fa;
if(x==y->ls)
{
if(y==z->ls)
Zig(y);
Zig(x);
}
else
{
if(y==z->rs)
Zag(y);
Zag(x);
}
}
x->Push_Up();
}
void Access(abcd *x)
{
abcd *y=null;
while(x!=null)
{
Splay(x);
x->rs=y;
x->Push_Up();
y=x;
x=x->fa;
}
}
abcd* Find_Root(abcd *x)
{
while(x->fa!=null)
x=x->fa;
return x;
}
void Move_To_Root(abcd *x)
{
Access(x);
Splay(x);
x->Reverse();
}
void Link(abcd *x,abcd *y)
{
Move_To_Root(x);
x->fa=y;
}
void Cut(abcd *x,abcd *y)
{
Move_To_Root(x);
Access(y);
Splay(y);
x->fa=null;
y->ls=null;
y->Push_Up();
}
int Query(abcd *x,abcd *y)
{
Move_To_Root(x);
Access(y);
Splay(y);
return y->minnum;
}
int n,m,q,type,ans;
int ntr[M],b[M],c[M],s[20][M];
void Insert(int p)
{
if(e[p].x==e[p].y)
{
ntr[p]=p;
return ;
}
abcd *x=tree[e[p].x],*y=tree[e[p].y];
if( Find_Root(x)==Find_Root(y) )
{
int temp=Query(x,y);
ntr[p]=temp;
Cut(tree[n+temp],tree[e[temp].x]);
Cut(tree[n+temp],tree[e[temp].y]);
free(tree[n+temp]);
}
tree[n+p]=new abcd(p);
Link(tree[n+p],tree[e[p].x]);
Link(tree[n+p],tree[e[p].y]);
}
void Build_Tree(int l,int r,int dpt)
{
int i,mid=l+r>>1;
int l1=l,l2=mid+1;
int left=mid-l+1;
if(l==r)
return ;
for(i=l;i<=r;i++)
left-=(ntr[i]<c[mid]);
for(i=l;i<=r;i++)
{
if(ntr[i]<c[mid]||ntr[i]==c[mid]&&left)
b[l1++]=ntr[i],s[dpt][i]=(i==l?1:s[dpt][i-1]+1),left-=(ntr[i]==c[mid]);
else
b[l2++]=ntr[i],s[dpt][i]=(i==l?0:s[dpt][i-1]);
}
memcpy( ntr+l , b+l , sizeof(ntr[0])*(r-l+1) );
Build_Tree(l,mid,dpt+1);
Build_Tree(mid+1,r,dpt+1);
}
int Get_Ans(int l,int r,int dpt,int x,int y,int val)
{
int mid=l+r>>1;
int l1=(x==l?0:s[dpt][x-1]),l2=s[dpt][y];
if(x>y)
return 0;
if(l==r)
return ntr[mid]<val;
if(val<=c[mid])
return Get_Ans(l,mid,dpt+1,l+l1,l+l2-1,val);
else
return l2-l1+Get_Ans(mid+1,r,dpt+1,(mid+1)+(x-l-l1),(mid+1)+(y-l+1-l2)-1,val);
}
int main()
{
int i,x,y;
cin>>n>>m>>q>>type;
for(i=1;i<=n;i++)
tree[i]=new abcd(INF);
for(i=1;i<=m;i++)
scanf("%d%d",&e[i].x,&e[i].y),Insert(i);
memcpy(c+1,ntr+1,sizeof(c[0])*m);
sort(c+1,c+m+1);
Build_Tree(1,m,0);
for(i=1;i<=q;i++)
{
scanf("%d%d",&x,&y);
x^=ans*type;y^=ans*type;
ans=n-Get_Ans(1,m,0,x,y,x);
printf("%d\n", ans );
}
}
BZOJ 3514 Codechef MARCH14 GERALD07加强版 Link-Cut-Tree+划分树的更多相关文章
- BZOJ 3514: Codechef MARCH14 GERALD07加强版 [LCT 主席树 kruskal]
3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec Memory Limit: 256 MBSubmit: 1312 Solved: 501 ...
- BZOJ 3514: Codechef MARCH14 GERALD07加强版( LCT + 主席树 )
从左到右加边, 假如+的边e形成环, 那么记下这个环上最早加入的边_e, 当且仅当询问区间的左端点> _e加入的时间, e对答案有贡献(脑补一下). 然后一开始是N个连通块, 假如有x条边有贡献 ...
- [BZOJ 3514]Codechef MARCH14 GERALD07加强版 (CHEF AND GRAPH QUERIES)
[BZOJ3514] Codechef MARCH14 GERALD07加强版 (CHEF AND GRAPH QUERIES) 题意 \(N\) 个点 \(M\) 条边的无向图,\(K\) 次询问保 ...
- BZOJ 3514: Codechef MARCH14 GERALD07加强版(LCT + 主席树)
题意 \(N\) 个点 \(M\) 条边的无向图,询问保留图中编号在 \([l,r]\) 的边的时候图中的联通块个数. \(K\) 次询问强制在线. \(1\le N,M,K \le 200,000\ ...
- BZOJ 3514 Codechef MARCH14 GERALD07加强版
题目链接:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3514 题意:给出一个图m条边.每次询问只加入编号在区间[L,R]之内的边有多少连通 ...
- 【刷题】BZOJ 3514 Codechef MARCH14 GERALD07加强版
Description N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. Input 第一行四个整数N.M.K.type,代表点数.边数.询问数以及询问是否加密. 接下来 ...
- BZOJ 3514: Codechef MARCH14 GERALD07加强版 (LCT维护最大生成树+主席树)
题意 给出nnn个点,mmm条边.多次询问,求编号在[l,r][l,r][l,r]内的边形成的联通块的数量,强制在线. 分析 LCTLCTLCT维护动态最大生成树,先将每条边依次加进去,若形成环就断掉 ...
- 【bzoj3514】Codechef MARCH14 GERALD07加强版 LCT+可持久化线段树
题目描述 N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. 输入 第一行四个整数N.M.K.type,代表点数.边数.询问数以及询问是否加密.接下来M行,代表图中的每条边 ...
- BZOJ3514 Codechef MARCH14 GERALD07加强版 LCT+可持久化线段树
自己独自想出来并切掉还是很开心的~ Code: #include <bits/stdc++.h> #define N 400005 #define inf 1000000000 #defi ...
随机推荐
- DotNetCasClient加载失败问题分析
最近公司在接入整理单点登录方案的时候,选择了CAS方案,实际版本采用了4.0.当我们把服务端附属完毕,基于.NET平台Web版的客户端DotNetCasClient进行定制化修改后,在测试环境通过.然 ...
- 在C#程序中,创建、写入、读取XML文件的方法
一.在C#程序中,创建.写入.读取XML文件的方法 1.创建和读取XML文件的方法,Values为需要写入的值 private void WriteXML(string Values) { //保存的 ...
- android黑科技系列——Wireshark和Fiddler分析Android中的TLS协议包数据(附带案例样本)
一.前言 在之前一篇文章已经介绍了一款网络访问软件的破解教程,当时采用的突破口是应用程序本身的一个漏洞,就是没有关闭日志信息,我们通过抓取日志获取到关键信息来找到突破口进行破解的.那篇文章也说到了,如 ...
- 1、Visual Studio Code安装及Hello Word
一.环境初始化 1.下载 Visual Studio Code对应版本安装 2.下载.NET Core 2.0 SDK安装 3.安装Mono Debug 完成后界面如下: 二.创建控制 ...
- 去除DialogFragment的背景阴影,背景色,标题栏
style中: <resources xmlns:android="http://schemas.android.com/apk/res/android"> <s ...
- DB2数据常用指令
************************************************************** 这个只是个人平时总结,如果有更好的欢迎告诉我,一起学习一起成长 ***** ...
- hibernate_03_session详解
获得session对象有两种方法: 1)openSession 2)getCurrentSession 如果使用的是getCurrentSession需要在hibernate.cfg.xml文件中进行 ...
- 【python】os.getcwd和getcwdu
print os.getcwd(), type(os.getcwd()) print os.getcwdu(), type(os.getcwdu()) 结果如下: C:\Users\Administr ...
- (转)Bootstrap 之 Metronic 模板的学习之路 - (2)源码分析之 head 部分
https://segmentfault.com/a/1190000006684122 下面,我们找个目录里面想对较小的文件来分析一下源码结构,我们可以看到,page_general_help.htm ...
- C# 带Cookies发送请求
#region --来自黄聪 void F1() { #region --创建cookies容器 添加Cookies和对应的URl(Hots主) CookieContainer cc = new Co ...