码迷,mamicode.com
首页 > 其他好文 > 详细

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

时间:2018-01-09 23:18:30      阅读:403      评论:0      收藏:0      [点我收藏+]

标签:log   body   ios   代码   std   etc   define   last   put   

3514: Codechef MARCH14 GERALD07加强版

Time Limit: 60 Sec  Memory Limit: 256 MB
Submit: 2023  Solved: 778
[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。

 

2016.2.26提高时限至60s

 

题解

这道题是一道思路好题(废话)

我们可以维护每条边关于加入时间的最大生成树

然后如果弹出一条边,记录这条边被谁弹出

然后显然对于区间 [l,r] ti 大于 r 的边一定不会被删除

并且所有 ti 小于等于 r 的边一定被删除

因为 ti 小于等于 r 的边一定在一个所有边编号都小于等于 r 并且都大

所以这段区间的答案为n-区间内大于r的数的个数

可持久化权值线段树维护下

代码

//by 减维
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<bitset>
#include<set>
#include<cmath>
#include<vector>
#include<set>
#include<map>
#include<ctime>
#include<algorithm>
#define ll long long
#define il inline
#define rg register
#define db double
#define inf (1<<30)
#define maxn 400005
#define mpr make_pair
#define eps 1e-8
using namespace std;

inline int read()
{
    int ret=0;bool fla=0;char ch=getchar();
    while((ch<0||ch>9)&&ch!=-)ch=getchar();
    if(ch==-){fla=1;ch=getchar();}
    while(ch>=0&&ch<=9){ret=ret*10+ch-0;ch=getchar();}
    return fla?-ret:ret;
}

struct edge{
    int x,y;
}e[maxn];

struct tree{
    int l,r,v;
}t[maxn<<5];

int n,m,q,tt,ans,cnt,rt[maxn],fa[maxn],son[maxn][2],val[maxn],rev[maxn],pos[maxn],tim[maxn];

il bool pdp(int x){return son[fa[x]][1]==x;}
il bool isrt(int x){return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}
il void rever(int x){rev[x]^=1;swap(son[x][0],son[x][1]);}

il void upda(int x)
{
    pos[x]=x;
    if(son[x][0]&&val[pos[son[x][0]]]<val[pos[x]]) pos[x]=pos[son[x][0]];
    if(son[x][1]&&val[pos[son[x][1]]]<val[pos[x]]) pos[x]=pos[son[x][1]];
}

il void pdn(int x)
{
    if(rev[x])
    {
        if(son[x][0]) rever(son[x][0]);
        if(son[x][1]) rever(son[x][1]);
        rev[x]=0;
    }
}

void pd(int x){if(!isrt(x)) pd(fa[x]);pdn(x);}

il void rot(int x)
{
    int f=fa[x],g=fa[f],o=pdp(x);
    if(!isrt(f)) son[g][pdp(f)]=x;fa[x]=g;
    son[f][o]=son[x][!o];fa[son[f][o]]=f;
    son[x][!o]=f;fa[f]=x;
    upda(f),upda(x);
}

il void splay(int x)
{
    pd(x);
    for(;!isrt(x);rot(x))
        if(!isrt(fa[x])) rot(pdp(fa[x])==pdp(x)?fa[x]:x);
}

il void acc(int x)
{
    for(int y=0;x;y=x,x=fa[x])
        splay(x),son[x][1]=y,upda(x);
}

il int find(int x)
{
    acc(x);splay(x);
    while(son[x][0]) pd(x),x=son[x][0];
    return x;
}

il void bert(int x){acc(x);splay(x);rever(x);}
il void spli(int x,int y){bert(x);acc(y);splay(y);}
il void cut(int x,int y){spli(x,y);fa[x]=son[y][0]=0;upda(y);}

il void link(int x,int y,int z)
{
    if(find(x)==find(y))
    {
        spli(x,y);
        int aa=pos[y];//printf("%d\n",aa);
        cut(e[aa-n].x,aa);cut(e[aa-n].y,aa);
        tim[aa-n]=z-n;
    }
    bert(x);fa[x]=z;
    bert(y);fa[y]=z;
}

void upd(int x)
{
    t[x].v=t[t[x].l].v+t[t[x].r].v;
}

void build(int l,int r,int las,int &now,int v)
{
    now=++cnt;t[now]=t[las];t[now].v++;
    if(l==r)return ;
    int mid=(l+r)>>1;
    if(v<=mid) build(l,mid,t[las].l,t[now].l,v);
    else build(mid+1,r,t[las].r,t[now].r,v);
}

int query(int l,int r,int x,int y,int v)
{
    if(l==v) return t[y].v-t[x].v;
    int mid=(l+r)>>1;
    if(v<=mid) return query(l,mid,t[x].l,t[y].l,v)+t[t[y].r].v-t[t[x].r].v;
    else return query(mid+1,r,t[x].r,t[y].r,v);
}

int main()
{
    n=read(),m=read();q=read(),tt=read();
    for(int i=0;i<=n;++i) val[i]=inf;
    for(int i=1;i<=m;++i)
    {
        e[i].x=read(),e[i].y=read();
        val[n+i]=i;tim[i]=m+1;
        if(e[i].x==e[i].y){tim[i]=i;continue;}
        link(e[i].x,e[i].y,n+i);
    }
    for(int i=1;i<=m;++i)
        build(0,m+1,rt[i-1],rt[i],tim[i]);
    for(int i=1,l,r;i<=q;++i)
    {
        l=read(),r=read();
        if(tt) l^=ans,r^=ans;
        printf("%d\n",ans=n-query(0,m+1,rt[l-1],rt[r],r+1));
    }
    return 0;
}

 

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

标签:log   body   ios   代码   std   etc   define   last   put   

原文地址:https://www.cnblogs.com/rir1715/p/8253874.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!