BZOJ 3514: Codechef MARCH14 GERALD07加强版( LCT + 主席树 )

时间:2022-08-31 12:14:12

BZOJ 3514: Codechef MARCH14 GERALD07加强版( LCT + 主席树 )

从左到右加边, 假如+的边e形成环, 那么记下这个环上最早加入的边_e, 当且仅当询问区间的左端点> _e加入的时间, e对答案有贡献(脑补一下). 然后一开始是N个连通块, 假如有x条边有贡献, 答案就是N-x. 用LCT维护加边, 可持久化线段树维护询问. O(NlogN)

------------------------------------------------------------------------------------

#include<cstdio>
#include<cctype>
#include<cstring>
#include<algorithm>
 
using namespace std;
 
const int maxn = 200009;
 
int N, M, Q, typ;
int ntr[maxn], par[maxn], sm[maxn], buf[16];
 
inline int getint() {
char c = getchar();
for(; !isdigit(c); c = getchar());
int ret = 0;
for(; isdigit(c); c = getchar())
ret = ret * 10 + c - '0';
return ret;
}
 
inline void putint(int x) {
if(!x) {
puts("0"); return;
}
int n = 0;
for(; x; x /= 10)
buf[n++] = x % 10;
while(n--)
putchar(buf[n] + '0');
puts("");
}
 
int Find(int x) {
return x == par[x] ? x : par[x] = Find(par[x]);
}
 
struct edge {
int u, v;
} e[maxn];
 
struct Node* Null;
 
struct Node {
Node *ch[2], *p, *fa, *mn;
bool iR, rev;
int n;
inline void setc(Node* c, int t) {
(ch[t] = c)->p = this;
}
inline void pd() {
if(rev) {
swap(ch[0], ch[1]);
ch[0]->rev ^= 1;
ch[1]->rev ^= 1;
rev = false;
}
}
inline void upd() {
mn = this;
if(ch[0] != Null && mn->n > ch[0]->mn->n) mn = ch[0]->mn;
if(ch[1] != Null && mn->n > ch[1]->mn->n) mn = ch[1]->mn;
}
inline int d() {
return this == p->ch[1];
}
inline void setR() {
fa = p, p = Null;
iR = true;
}
} pool[maxn << 1], *T, *V[maxn], *stk[maxn << 1];
 
void Init_LCT() {
T = pool;
T->ch[0] = T->ch[1] = T;
T->fa = T->p = T->mn = T;
T->n = maxn;
Null = T++;
}
 
Node* Newnode(int n) {
T->n = n;
T->ch[0] = T->ch[1] = Null;
T->fa = T->p = Null;
T->iR = true, T->rev = false;
return T++;
}
 
void Rot(Node* t) {
Node* p = t->p;
p->pd(), t->pd();
int d = t->d();
p->p->setc(t, p->d());
p->setc(t->ch[d ^ 1], d);
t->setc(p, d ^ 1);
p->upd();
if(p->iR) {
p->iR = false;
t->iR = true;
t->fa = p->fa;
}
}
 
void Splay(Node* t) {
int n = 0;
for(Node* o = t; o != Null; o = o->p) stk[n++] = o;
while(n--) stk[n]->pd();
for(Node* p = t->p; p != Null; p = t->p) {
if(p->p != Null)
p->d() != t->d() ? Rot(t) : Rot(p);
Rot(t);
}
t->upd();
}
 
void Access(Node* t) {
for(Node* o = Null; t != Null; o = t, t = t->fa) {
Splay(t);
t->ch[1]->setR();
t->setc(o, 1);
}
}
 
void makeRoot(Node* t) {
Access(t);
Splay(t);
t->rev ^= 1;
}
 
Node* Path(Node* u, Node* v) {
makeRoot(u);
Access(v), Splay(v);
return v;
}
 
void Join(Node* u, Node* v) {
makeRoot(u);
u->fa = v;
}
 
void Cut(Node* u, Node* v) {
makeRoot(u);
Access(v), Splay(v);
u->p = Null, u->setR();
v->setc(Null, 0), v->upd();
}
 
namespace F {
int Val;
struct Node {
Node *lc, *rc;
int n;
} pool[maxn * 80], *pt, *Null, *Root[maxn];
void Init() {
pt = pool;
pt->lc = pt->rc = pt;
pt->n = 0;
Root[0] = Null = pt++;
}
Node* Modify(Node* t, int l, int r) {
Node* o = pt++;
o->n = t->n + 1;
if(l != r) {
int m = (l + r) >> 1;
if(Val <= m) {
o->lc = Modify(t->lc, l, m);
o->rc = t->rc;
} else {
o->lc = t->lc;
o->rc = Modify(t->rc, m + 1, r);
}
}
return o;
}
}
 
int main() {
N = getint(), M = getint();
Q = getint(), typ = getint();
Init_LCT();
for(int i = 0; i < N; i++)
par[i] = i, V[i] = Newnode(maxn);
for(int i = 1; i <= M; i++) {
int &u = e[i].u, &v = e[i].v;
u = getint() - 1, v = getint() - 1;
if(u == v) {
ntr[i] = maxn;
continue;
}
int _u = Find(u), _v = Find(v);
Node* t = Newnode(i);
if(_u == _v) {
Node* mn = Path(V[u], V[v])->mn;
Cut(V[e[mn->n].u], mn);
Cut(V[e[mn->n].v], mn);
ntr[i] = mn->n;
} else {
ntr[i] = 0;
par[_u] = _v;
}
Join(t, V[u]), Join(t, V[v]);
}
F::Init();
for(int i = 1; i <= M; i++) if(ntr[i] >= 1 && ntr[i] <= M) {
F::Val = ntr[i];
F::Root[i] = F::Modify(F::Root[i - 1], 1, M);
} else 
F::Root[i] = F::Root[i - 1];
sm[0] = 0;
for(int i = 1; i <= M; i++)
sm[i] = sm[i - 1] + !ntr[i];
int ans = 0, l, r;
while(Q--) {
l = getint(), r = getint();
if(typ)
l ^= ans, r ^= ans;
int p = l - 1;
ans = sm[r] - sm[p];
F::Node *L = F::Root[p], *R = F::Root[r];
l = 1, r = M;
while(l < r) {
int m = (l + r) >> 1;
if(m <= p) {
ans += R->lc->n - L->lc->n;
L = L->rc, R = R->rc;
l = m + 1;
} else {
L = L->lc, R = R->lc;
r = m;
}
}
putint(ans = N - ans);
}
return 0;
}

------------------------------------------------------------------------------------

3514: Codechef MARCH14 GERALD07加强版

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 685  Solved: 232
[Submit][Status][Discuss]

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。

Source

BZOJ 3514: Codechef MARCH14 GERALD07加强版( LCT + 主席树 )的更多相关文章

  1. BZOJ 3514&colon; Codechef MARCH14 GERALD07加强版 &lbrack;LCT 主席树 kruskal&rsqb;

    3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1312  Solved: 501 ...

  2. &lbrack;BZOJ3514&rsqb;CodeChef MARCH14 GERALD07加强版&lpar;LCT&plus;主席树&rpar;

    3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 2177  Solved: 834 ...

  3. BZOJ 3514&colon; Codechef MARCH14 GERALD07加强版 &lpar;LCT维护最大生成树&plus;主席树&rpar;

    题意 给出nnn个点,mmm条边.多次询问,求编号在[l,r][l,r][l,r]内的边形成的联通块的数量,强制在线. 分析 LCTLCTLCT维护动态最大生成树,先将每条边依次加进去,若形成环就断掉 ...

  4. 【BZOJ3514】Codechef MARCH14 GERALD07加强版 LCT&plus;主席树

    题解: 还是比较简单的 首先我们的思路是 确定起点 然后之后贪心的选择边(也就是越靠前越希望选) 我们发现我们只需要将起点从后向前枚举 然后用lct维护连通性 因为强制在线,所以用主席树记录状态就可以 ...

  5. BZOJ 3514 Codechef MARCH14 GERALD07加强版 Link-Cut-Tree&plus;划分树

    题目大意: 给定n个点m条边的无向图.求问当图中仅仅有[编号在[l,r]区间内]的边存在时图中的联通块个数 强制在线 注意联通块是指联通了就是同一块,不是Tarjan求的那种块 看到这题的那一刻我就想 ...

  6. 【BZOJ-3514】Codechef MARCH14 GERALD07加强版 LinkCutTree &plus; 主席树

    3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1288  Solved: 490 ...

  7. &lbrack;BZOJ 3514&rsqb;Codechef MARCH14 GERALD07加强版 &lpar;CHEF AND GRAPH QUERIES&rpar;

    [BZOJ3514] Codechef MARCH14 GERALD07加强版 (CHEF AND GRAPH QUERIES) 题意 \(N\) 个点 \(M\) 条边的无向图,\(K\) 次询问保 ...

  8. BZOJ 3514&colon; Codechef MARCH14 GERALD07加强版(LCT &plus; 主席树)

    题意 \(N\) 个点 \(M\) 条边的无向图,询问保留图中编号在 \([l,r]\) 的边的时候图中的联通块个数. \(K\) 次询问强制在线. \(1\le N,M,K \le 200,000\ ...

  9. 【刷题】BZOJ 3514 Codechef MARCH14 GERALD07加强版

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

随机推荐

  1. Java豆瓣电影爬虫——小爬虫成长记(附源码)

    以前也用过爬虫,比如使用nutch爬取指定种子,基于爬到的数据做搜索,还大致看过一些源码.当然,nutch对于爬虫考虑的是十分全面和细致的.每当看到屏幕上唰唰过去的爬取到的网页信息以及处理信息的时候, ...

  2. 解决&colon; org&period;iq80&period;leveldb&period;DBException&colon; IO error&colon; C&colon;&bsol;data&bsol;trie&bsol;000945&period;sst&colon; Could not create random access file&period;

    以太坊MPT树的持久化层是采用了leveldb数据库,然而在抽取MPT树代码运行过程中,进行get和write操作时却发生了错误: Caused by: org.fusesource.leveldbj ...

  3. &lbrack;ACM&lowbar;动态规划&rsqb; Alignment (将军排队&rpar;

    http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28415#problem/F 题目大意:有n个士兵排成一列,将军想从中抽出最少人数使队伍中 ...

  4. Redis配置以及通过C&num;访问小试

    首先安装一个Ubuntu14.04的虚拟机用来安装Redis.Ubuntu的Unity在虚拟机里面卡爆了,可以通过如下方法安装传统的Gnome界面: sudo aptitude install gno ...

  5. linux命令:rmdir

    1.命令介绍: rmdir只能用来删除空目录,删除某目录时必须对其父目录有读权限. 2.命令选项: rmdir [选项] 目录 3.命令参数: -p --parent 递归删除目录dirname,当子 ...

  6. 《c程序设计语言》读书笔记--反转字符串

    #include "stdio.h" #define Num 100 void reverse(char words[]) { int i, j, c, n=0; while(wo ...

  7. jQuery ajax 传递数组到struts2

    使用jQuery的$.ajax()方法进行异步交互时,如果传递的数据有数组(例如传输checkbox数据),Action中经常会接受不到数据. 此时应该注意一下data中数组的写法,例如: //组合成 ...

  8. 分享&period;net常见的内存泄露及解决方法

    分享.net常见的内存泄露及解决方法 关于内存泄漏的问题,之前也为大家介绍过,比如:<C++中内存泄漏的检测方法介绍>,是关于C++内存泄漏的.今天为大家介绍的是关于.NET内存泄漏的问题 ...

  9. Lynis 2&period;2&period;0 :面向Linux系统的安全审查和扫描工具

    Lynis是一款功能非常强大的开源审查工具,面向类似Unix/Linux的操作系统.它可以扫描系统,查找安全信息.一般的系统信息.已安装软件及可用软件信息.配置错误.安全问题.没有设密码的用户帐户.错 ...

  10. Mac搭建Hadoop源码阅读环境

    1.本次Hadoop源码阅读环境使用的阅读工具是idea,Hadoop版本是2.7.3.需要安装的工具包括idea.jdk.maven.protobuf等 2.jdk,使用的版本是1.8版,在jdk官 ...