Codechef MARCH14 GERALD07加强版

强制在线不代表不能预处理!

考虑暴力怎么干?

开始n个联通块。now=n

不断加入边,如果连接两个联通块,--now

否则不动。

后者的前提是和[l,id-1]的边构成环

所以,我们考虑每个[l,r]中出现的边能否第一次连接两个联通块

预处理:

编号从小到大加入每条边,LCT维护树上“边”编号最小值和最小值位置

如果加入边e没有环,那么说明无论什么时候[l,r]询问包含e的时候,e总能是第一个连接两个联通块的边,设ti[e]=0,表示不能替换边

如果会成环,那么把编号最小的边删掉,ti[i]=被删边的编号。意义是,只有[l,r]不包含这条被删除的边的时候,e才会贡献。

    如果包含,那么这个环一定会连出来;如果不包含,e和这个环上其他的边不会构成环,加入e的时候有贡献。(如果会构成环,那么环上边和被删边之前也能构成环,矛盾)

所以,ti[i]在不在[l,r]之中,唯一对应了i能否真正连接两个联通块!

所以对于询问,主席树维护即可。[l,r]中,ti[i]<l的数的个数sum,n-sum就是ans

实现细节:
LCT的编号别和原边的编号混了。。。。

mi是最小边编号(最小值),id是最小值的lct点的编号!

调半天~~~

吸取重组病毒的教训,把主席树封装进namespace~~

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define numb (ch^‘0‘)
using namespace std;
typedef long long ll;
il void rd(int &x){
    char ch;x=0;bool fl=false;
    while(!isdigit(ch=getchar()))(ch==‘-‘)&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);
    (fl==true)&&(x=-x);
}
namespace Miracle{
const int N=200000+5;
const int inf=0x3f3f3f3f;
struct bian{
    int x,y;
}e[N];
int n,m,k,typ;
int ti[N];
namespace seg{
#define mid ((l+r)>>1)
struct node{
    int ls,rs;
    int val;
}t[N*22];
int cnt;
int rt[N];
void upda(int &x,int y,int l,int r,int to){
    x=++cnt;
    t[x].val=t[y].val+1;
    if(l==r) return;
    t[x].ls=t[y].ls,t[x].rs=t[y].rs;
    if(to<=mid) upda(t[x].ls,t[y].ls,l,mid,to);
    if(mid<to) upda(t[x].rs,t[y].rs,mid+1,r,to);
}
int query(int x,int y,int l,int r,int L,int R){
    //cout<<" l r "<<l<<" "<<r<<" : "<<t[x].val<<" "<<t[y].val<<" "<<L<<" "<<R<<endl;
    if(L<=l&&r<=R){
        //cout<<" l r "<<l<<" "<<r<<" : "<<t[x].val<<" "<<t[y].val<<" "<<L<<" "<<R<<endl;
        return t[x].val-t[y].val;
    }
    int ret=0;
    if(L<=mid) ret+=query(t[x].ls,t[y].ls,l,mid,L,R);
    if(mid<R) ret+=query(t[x].rs,t[y].rs,mid+1,r,L,R);
    return ret;
}
void add(int x,int to){
    upda(rt[x],rt[x-1],0,m,to);
}
}
namespace lct{
#define ls t[x].ch[0]
#define rs t[x].ch[1]
struct node{
    int ch[2];
    int fa,r;
    int id;
    int mi;
    int d;
}t[2*N];
int sta[N];
int cnt;
bool nrt(int x){
    return (t[t[x].fa].ch[0]==x||t[t[x].fa].ch[1]==x);
}
void pushup(int x){
    if(t[t[x].ch[0]].mi<=t[x].d&&t[t[x].ch[0]].mi<=t[t[x].ch[1]].mi){
        t[x].mi=t[t[x].ch[0]].mi;
        t[x].id=t[t[x].ch[0]].id;
    }
    else if(t[t[x].ch[1]].mi<=t[x].d&&t[t[x].ch[1]].mi<=t[t[x].ch[0]].mi){
        t[x].mi=t[t[x].ch[1]].mi;
        t[x].id=t[t[x].ch[1]].id;
    }
    else t[x].mi=t[x].d,t[x].id=x;
}
void rev(int x){
    swap(t[x].ch[0],t[x].ch[1]);
    t[x].r^=1;
}
void pushdown(int x){
    if(t[x].r){
        rev(t[x].ch[1]),rev(t[x].ch[0]);
        t[x].r=0;
    }
}
void rotate(int x){
    int y=t[x].fa,d=t[y].ch[1]==x;
    t[t[y].ch[d]=t[x].ch[!d]].fa=y;
    if(nrt(y)) t[t[x].fa=t[y].fa].ch[t[t[y].fa].ch[1]==y]=x;
    else t[x].fa=t[y].fa;
    t[t[x].ch[!d]=y].fa=x;
    pushup(y);
}
void splay(int x){
    int y=x,z=0;
    sta[++z]=y;
    while(nrt(y)) y=t[y].fa,sta[++z]=y;
    while(z) pushdown(sta[z--]);

    while(nrt(x)){
        y=t[x].fa,z=t[y].fa;
     //   cout<<"splaying "<<x<<" "<<y<<" "<<z<<endl;
        if(nrt(y)){
            rotate(((t[z].ch[1]==y)==(t[y].ch[1]==x))?y:x);
        }
        rotate(x);
    }
    pushup(x);
}
void access(int x){
    for(reg y=0;x;y=x,x=t[x].fa){

        splay(x);t[x].ch[1]=y;pushup(x);
    //    cout<<" access xx "<<x<<" "<<t[x].fa<<endl;
    }
}
void makert(int x){
    access(x);splay(x);rev(x);
}
int findrt(int x){
    access(x);splay(x);
//    cout<<" after splay "<<x<<endl;
    pushdown(x);
    while(t[x].ch[0]) {
        x=t[x].ch[0],pushdown(x);
//        cout<<"findrt xx "<<x<<endl;
    }
    splay(x);
    return x;
}
int link(int x,int y,int d){
//    cout<<" link "<<x<<" "<<y<<" : "<<d<<" cnt "<<cnt<<endl;
    makert(x);
//    cout<<" makert "<<endl;
    ++cnt;
    t[cnt].d=d;
    t[cnt].id=cnt;
    t[cnt].mi=d;
    if(findrt(y)!=x){
    //    cout<<" new "<<endl;
        access(y);splay(y);
        t[x].fa=cnt;
        t[cnt].fa=y;
        return 0;
    }
    pushup(x);
    splay(x);
    int kil=t[x].id;
    int lp=t[x].mi;
//    cout<<" ---------------------kil "<<kil<<endl;
    splay(kil);
//    cout<<" kilfa "<<t[kil].fa<<endl;
    t[t[kil].ch[0]].fa=0;
    t[t[kil].ch[1]].fa=0;
    makert(x);
    splay(x);splay(y);
    t[x].fa=cnt;
    t[cnt].fa=y;
    //cout<<" t[x].id "<<t[x].id<<" t[y].id "<<t[y].id<<endl;
    return lp;
}
}
int main(){
    lct::t[0].id=-1;
    lct::t[0].d=inf;
    lct::t[0].mi=inf;
    rd(n);rd(m);rd(k);rd(typ);
    for(reg i=1;i<=n;++i) lct::t[i].d=inf,lct::t[i].id=-1,lct::t[i].mi=inf;
    lct::cnt=n;
    int x,y;
    for(reg i=1;i<=m;++i){
        rd(x);rd(y);
        if(x!=y) ti[i]=lct::link(x,y,i);
        else ti[i]=i;
        //cout<<" ii "<<i<<" "<<ti[i]<<endl;
    }
    for(reg i=1;i<=m;++i){
        seg::add(i,ti[i]);
    }
    int l,r;
    int las=0;
    while(k--){
        rd(l);rd(r);
        if(typ==1) l^=las,r^=las;
        int tmp=seg::query(seg::rt[r],seg::rt[l-1],0,m,0,l-1);
        printf("%d\n",n-tmp);
        las=n-tmp;
    }
    return 0;
}

}
signed main(){
//freopen("data.in","r",stdin);
//    freopen("my.out","w",stdout);
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
   Date: 2018/12/30 21:24:18
*/

原文地址:https://www.cnblogs.com/Miracevin/p/10201419.html

时间: 2024-10-07 20:54:17

Codechef MARCH14 GERALD07加强版的相关文章

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

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行,每行两个整

[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

【BZOJ3514】Codechef MARCH14 GERALD07加强版(LCT)

题意:N个点M条边的无向图,q次询问保留图中编号在[l,r]的边的时候图中的联通块个数. 询问加密,强制在线 n,m,q<=200000 题意:RYZ作业 以下转载自hzwer http://hzwer.com/4358.html 本人实力有限难以清晰描述 有一个比较猎奇的做法:首先把边依次加到图中,若当前这条边与图中的边形成了环,那么把这个环中最早加进来的边弹出去并将每条边把哪条边弹了出去记录下来:ntr[i] = j,特别地,要是没有弹出边,ntr[i] = 0;这个显然是可以用LCT来弄的

[bzoj3514]: Codechef MARCH14 GERALD07加强版

跪了半天题解才会..TAT http://hzwer.com/4358.html 1 #include<cstdio> 2 #include<iostream> 3 #include<cstring> 4 using namespace std; 5 const int maxn=200233<<1; 6 const int inf=1000023333; 7 struct zs{ 8 int u,v; 9 }e[200233]; 10 int ch[max

【bzoj3514】Codechef MARCH14 GERALD07加强版

hzwer上少有的几道需要建一下模的 要不是有这么几道题 我都觉得lct只会考裸题了呢 题解看hzwer吧 http://hzwer.com/4358.html 唯一蛋疼的就是为了处理0这个呵呵的位置,和严格小于,我把ntr数组全部+2,然后l+1,这样建树的时候就要写m+2了= =好蛋疼 1 #include<iostream> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cstdio> 5 #in

【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$数组有什么用呢,我

BZOJ3514 Codechef MARCH14 GERALD07加强版 LCT

欢迎访问~原文出处--博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ3514 题意概括 N个点M条边的无向图,询问保留图中编号在[l,r]的边的时候图中的联通块个数. N,M,Q<=200000 题解 http://hzwer.com/4358.html 这题hzwer还是写的很好的-- 代码 #include <cstring> #include <cstdio> #include <cstdlib> #include <al

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>