从左到右加边, 假如+的边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: Codechef MARCH14 GERALD07加强版 [LCT 主席树 kruskal]

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

  2. [BZOJ3514]CodeChef MARCH14 GERALD07加强版(LCT+主席树)

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

  3. BZOJ 3514: Codechef MARCH14 GERALD07加强版 (LCT维护最大生成树+主席树)

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

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

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

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

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

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

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

  7. [BZOJ 3514]Codechef MARCH14 GERALD07加强版 (CHEF AND GRAPH QUERIES)

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

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

    题意 \(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. SQL Server 获取服务器信息

    最近做了一个小工具,里面涉及到一些取SQL Server 服务器信息的一些东西,找了好久,找到一个不错的,贴出来分享. 系统函数 SERVERPROPERTY ( propertyname ) 包含要 ...

  2. Oracle backgroup processes

    PMON: Process Monitor 用自己主动注冊动态监听,处理异常进程. SMON: System Monitor 用于instance recovery. LCKn:仅使用于RAC数据库, ...

  3. google自定义站内搜索

    ttps://www.google.com/cse/docs/cref.html?hl=zh-cn 重要表单参数: action 字段:您希望存储结果的网址(在该例中,我们使用 http://www. ...

  4. windows通过cmd重新启动网卡

    ipconfig/release ipconfig/renew

  5. HDU 1423 Greatest Common Increasing Subsequence(最长公共上升LCIS)

    HDU 1423 Greatest Common Increasing Subsequence(最长公共上升LCIS) http://acm.hdu.edu.cn/showproblem.php?pi ...

  6. dropDownList之"请选择",同时设置默认选项

    dropDownList.Items.Insert(0, new ListItem("--请选择--", "-1"));dropDownList.Selecte ...

  7. wcf系列学习5天速成——第五天 服务托管

    今天是系列的终结篇,当然要分享一下wcf的托管方面的知识. wcf中托管服务一般有一下四种: Console寄宿:             利于开发调试,但不是生产环境中的最佳实践. winform寄 ...

  8. ActionBar隐藏修改图标和标题

    有时候在一些子页面或者内容页面,不需要显示ActionBar的标题栏图标.可用如下方式进行设置. 首先获取到ActionBar对象 ActionBar actionBar=getActionBar() ...

  9. HBASE学习笔记--shell

    Hbase shell 启动 下载安装hbase client包,填写相关配置后进入,配置相关说明可以参见配置篇 指令:./bin/hbase shell 状态及配置信息查询 查询服务器状态 stat ...

  10. C#用网易邮箱发送邮件(同步异步)

    SmtpClient smtpServer = new SmtpClient("smtp.163.com"); smtpServer.Port = ; smtpServer.Cre ...