BZOJ_3514_Codechef MARCH14 GERALD07加强版_主席树+LCT

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。



把这m条边按顺序插进去,维护边的编号最小的边的编号。

当出现两个点连通时把路径上编号最小的删掉,并记录下每条边删除的时间t。

对于询问l~r,假设这些边放进去,也会有一些边被删除。

连通块个数=n-((r-l+1)-被删除的边数)。

然后知道被删除的边数刚好是t小于等于r的那些边,主席树查一下即可。

代码:

#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define N 400050
#define ls ch[p][0]
#define rs ch[p][1]
#define get(x) (ch[f[x]][1]==x)
int ch[N][2],f[N],rev[N],n,m,k,siz[N*30],t[N],val[N],mx[N],tot,cnt,lson[N*30],rson[N*30];
int xx[N],yy[N],root[N];
inline bool isrt(int p) {
    return ch[f[p]][0]!=p&&ch[f[p]][1]!=p;
}
inline void pushup(int p) {
    mx[p]=p;
    if(val[mx[ls]]>val[mx[p]]) mx[p]=mx[ls];
    if(val[mx[rs]]>val[mx[p]]) mx[p]=mx[rs];
}
inline void pushdown(int p) {
    if(rev[p]) {
        swap(ch[ls][0],ch[ls][1]); swap(ch[rs][0],ch[rs][1]);
        rev[ls]^=1; rev[rs]^=1; rev[p]=0;
    }
}
void update(int p) {
    if(!isrt(p)) update(f[p]); pushdown(p);
}
void rotate(int x) {
    int y=f[x],z=f[y],k=get(x);
    if(!isrt(y)) ch[z][ch[z][1]==y]=x;
    ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
    ch[x][!k]=y; f[y]=x; f[x]=z;
    pushup(y); pushup(x);
}
void splay(int x) {
    update(x);
    for(int d;d=f[x],!isrt(x);rotate(x))
        if(!isrt(d))
            rotate(get(d)==get(x)?d:x);
}
void access(int p) {
    int t=0;
    while(p) splay(p),rs=t,pushup(p),t=p,p=f[p];
}
void makeroot(int p) {
    access(p); splay(p); swap(ls,rs); rev[p]^=1;
}
void link(int x,int p) {
    makeroot(x); splay(p); f[x]=p;
}
void cut(int x,int p) {
    makeroot(x); access(p); splay(p); ls=f[x]=0;
}
int find(int p) {
    access(p); splay(p); while(ls) pushdown(p),p=ls;
    return p;
}
void insert(int &y,int x,int l,int r,int v) {
    y=++tot; siz[y]=siz[x]+1;
    if(l==r) return ;
    int mid=(l+r)>>1;
    if(v<=mid) rson[y]=rson[x],insert(lson[y],lson[x],l,mid,v);
    else lson[y]=lson[x],insert(rson[y],rson[x],mid+1,r,v);
}
int query(int x,int y,int l,int r,int k) {
    if(k>=r) return siz[x]-siz[y];
    int mid=(l+r)>>1,re=0;
    if(1<=mid) re+=query(lson[x],lson[y],l,mid,k);
    if(k>mid) re+=query(rson[x],rson[y],mid+1,r,k);
    return re;
}
int inq(int x,int p) {
    makeroot(x); access(p); splay(p); return mx[p];
}
int main() {
    int type;
    scanf("%d%d%d%d",&n,&m,&k,&type);
    int i,x,y;
    cnt=n;
    for(i=1;i<=n;i++) mx[i]=i;
    for(i=1;i<=m;i++) {
        cnt++;
        scanf("%d%d",&x,&y); xx[cnt]=x; yy[cnt]=y;
        if(x==y) {
            t[i]=i; continue;
        }
        int t1=find(x),t2=find(y);
        if(t1!=t2) {
            val[cnt]=m-i+1; mx[cnt]=cnt;
            link(x,cnt); link(cnt,y);
        }else {
            val[cnt]=m-i+1; mx[cnt]=cnt;
            int d=inq(x,y);
            //printf("%d\n",val[d]);
            t[m-val[d]+1]=i;

            cut(xx[d],d); cut(d,yy[d]);
            link(x,cnt); link(cnt,y);
        }
    }
    for(i=1;i<=m;i++) {
        if(!t[i]) t[i]=m+1;
        insert(root[i],root[i-1],1,m+1,t[i]);
    }
    int ans=0;
    while(k--) {
        scanf("%d%d",&x,&y);
        if(!type) ans=0;
        x^=ans; y^=ans;
        ans=n-y+x-1+query(root[y],root[x-1],1,m+1,y);
        printf("%d\n",ans);
    }
    //for(i=1;i<=m;i++) printf("%d\n",t[i]);

}

原文地址:https://www.cnblogs.com/suika/p/8968008.html

时间: 2024-11-07 03:43:28

BZOJ_3514_Codechef MARCH14 GERALD07加强版_主席树+LCT的相关文章

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

3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 2177  Solved: 834[Submit][Status][Discuss] Description N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. Input 第一行四个整数N.M.K.type,代表点数.边数.询问数以及询问是否加密.接下来M行,代表图中的每条边.接下来K行,每行两个整数L

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

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

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

3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 2023  Solved: 778[Submit][Status][Discuss] Description N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. Input 第一行四个整数N.M.K.type,代表点数.边数.询问数以及询问是否加密. 接下来M行,代表图中的每条边. 接下来K行,每行两个整

bzoj 3514 Codechef MARCH14 GERALD07加强版 主席树+LCT

题面 题目传送门 解法 思路很妙 参见hzwer的题解 主席树+LCT--真是个毒瘤的组合 时间复杂度:\(O((m+q)\ log\ m)\) 代码 #include <bits/stdc++.h> #define N 400010 using namespace std; template <typename node> void chkmax(node &x, node y) {x = max(x, y);} template <typename node>

BZOJ 3514: Codechef MARCH14 GERALD07加强版

3514: Codechef MARCH14 GERALD07加强版 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 1356  Solved: 514[Submit][Status][Discuss] Description N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. Input 第一行四个整数N.M.K.type,代表点数.边数.询问数以及询问是否加密.接下来M行,代表图中的每条边.接下来K行,每行两个整数L

【bzoj3514】 Codechef MARCH14 GERALD07加强版

http://www.lydsy.com/JudgeOnline/problem.php?id=3514 (题目链接) 题意 给出$n$个点$m$条边的无向图,询问保留图中编号在$[l,r]$的边的时候图中的连通块的个数. Solution 将边的编号作为权值用LCT维护一个最大生成树,同时记录一下加入当前边$i$会把哪一条原本在生成树中的边踢掉,记作$ntr[i]$.如果不会踢掉任意一条边,那么$ntr[i]=0$.如果$i$是自环,那么$ntr[i]=i$. 求出$ntr$数组有什么用呢,我

Codechef MARCH14 GERALD07加强版

强制在线不代表不能预处理! 考虑暴力怎么干? 开始n个联通块.now=n 不断加入边,如果连接两个联通块,--now 否则不动. 后者的前提是和[l,id-1]的边构成环 所以,我们考虑每个[l,r]中出现的边能否第一次连接两个联通块 预处理: 编号从小到大加入每条边,LCT维护树上"边"编号最小值和最小值位置 如果加入边e没有环,那么说明无论什么时候[l,r]询问包含e的时候,e总能是第一个连接两个联通块的边,设ti[e]=0,表示不能替换边 如果会成环,那么把编号最小的边删掉,ti

BZOJ_4448_[Scoi2015]情报传递_主席树

Description 奈特公司是一个巨大的情报公司,它有着庞大的情报网络.情报网络中共有n名情报员.每名情报员口J-能有 若T名(可能没有)下线,除1名大头日外其余n-1名情报员有且仅有1名上线.奈特公司纪律森严,每 名情报员只能与自己的上.下线联系,同时,情报网络中仟意两名情报员一定能够通过情报网络传递情报. 奈特公司每天会派发以下两种任务中的一个任务: 1.搜集情报:指派T号情报员搜集情报 2.传递情报:将一条情报从X号情报员传递给Y号情报员 情报员最初处于潜伏阶段,他们是相对安全的,我们

BZOJ_3772_精神污染_主席树

Description 兵库县位于日本列岛的中央位置,北临日本海,南面濑户内海直通太平洋,中央部位是森林和山地,与拥有关西机场的大阪府比邻而居,是关西地区面积最大的县,是集经济和文化于一体的一大地区,是日本西部门户,海陆空交通设施发达.濑户内海沿岸气候温暖,多晴天,有日本少见的贸易良港神户港所在的神户市和曾是豪族城邑“城下町”的姬路市等大城市,还有以疗养地而闻名的六甲山地等. 兵库县官方也大力发展旅游,为了方便,他们在县内的N个旅游景点上建立了n-1条观光道,构成了一棵图论中的树.同时他们推出了