zoukankan      html  css  js  c++  java
  • CF1556G Gates to Another World 题解

    Codeforces
    Luogu

    Description.

    给定一张图,有 \(2^{n}\) 个点,存在边 \((u,v)\) 当且仅当 \(\text{bitcount}(u\oplus v)=1\)
    要求支持区间删点,询问两点是否联通。

    \(n\le 50,q\le 50000\)

    Solution.

    首先考虑一个一个点都没有 ban 掉的集合,它肯定是两两联通的。
    然后总点数是 \(2^{50}\) 级别的,连 \(O(n)\) 都直接炸。
    定义一张图是完全的当且仅当它有 \(2^k\) 个点和 \(k\cdot2^{k-1}\) 条边。
    我们可以对所有点都被 ban 掉之后剩下的点,把所有完全子图缩成一个点。
    点数肯定是 \(O(m\cdot n)\) 的,证明的话就考虑线段树每次产生 \(\log 2^n\) 个点。
    然后直接用线段树维护,边数是 \(O(m^2\cdot n)\) 的,可以通过。

    Coding.

    点击查看小学生代码
    //是啊,你就是那只鬼了,所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<48||c>57;c=getchar()) if(!(c^45)) f=1;
    	for(;c>=48&&c<=57;c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	f?x=-x:x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
    struct segm{int ls,rs,lz;}T[5000005];int tt,m;ll n;
    struct qwq{char ch[6];ll l,r;}q[50005];int fa[5000005];
    vector<pair<int,int> >e[5000005];char rs[50005];
    inline int getf(int x) {return fa[x]==x?x:fa[x]=getf(fa[x]);}
    inline void mrg(int x,int y) {x=getf(x),y=getf(y);if(x^y) fa[x]=y;}
    inline char chk(int x,int y) {return getf(x)==getf(y);}
    inline void pushdw(int x)
    {
    	int v=T[x].lz;if(!T[x].lz) return;else T[x].lz=0;
    	T[T[x].ls?T[x].ls:T[x].ls=++tt].lz=v;
    	T[T[x].rs?T[x].rs:T[x].rs=++tt].lz=v;
    }
    inline void modif(int x,ll l,ll r,ll dl,ll dr,int dv)
    {
    	if(l>dr||dl>r) return;else if(dl<=l&&r<=dr) return T[x].lz=dv,void();
    	pushdw(x),modif(T[x].ls,l,(l+r)>>1,dl,dr,dv),modif(T[x].rs,((l+r)>>1)+1,r,dl,dr,dv);
    }
    inline void solve(int x,int y)
    {
    	//printf("! %d %d\n",x,y);for(int i=100000000;i--;);
    	if(T[x].lz&&T[y].lz) return e[min(T[x].lz,T[y].lz)].push_back(make_pair(x,y)),void();
    	if(T[x].lz) return solve(x,T[y].ls),solve(x,T[y].rs);
    	if(T[y].lz) return solve(T[x].ls,y),solve(T[x].rs,y);
    	return solve(T[x].ls,T[y].ls),solve(T[x].rs,T[y].rs);
    }
    inline int fnd(int x,ll l,ll r,ll dw)
    {
    	if(T[x].lz) return x;
    	if(dw<=((l+r)>>1)) return fnd(T[x].ls,l,(l+r)>>1,dw);
    	else return fnd(T[x].rs,((l+r)>>1)+1,r,dw);
    }
    int main()
    {
    	read(n,m),n=1ll<<n,n--,++tt,T[1].lz=m+1;
    	for(int i=1;i<=m;i++) scanf("%s",q[i].ch),read(q[i].l),read(q[i].r);
    	for(int i=1;i<=m;i++) if(*q[i].ch=='b') modif(1,0,n,q[i].l,q[i].r,i);
    	//for(int i=1;i<=tt;i++) if(T[i].ls) printf("%d %d\n",i,T[i].ls);
    	//for(int i=1;i<=tt;i++) if(T[i].rs) printf("%d %d\n",i,T[i].rs);
    	//for(int i=1;i<=tt;i++) printf("%d%c",T[i].lz,i==tt?'\n':' ');
    	for(int i=1;i<=tt;i++) if(T[i].ls&&T[i].rs) solve(T[i].ls,T[i].rs);
    	for(int i=1;i<=tt;i++) fa[i]=i;
    	for(int i=m;i>=1;i--)
    	{
    		for(auto x:e[i+1]) mrg(x.first,x.second);
    		if(*q[i].ch=='a') rs[i]=chk(fnd(1,0,n,q[i].l),fnd(1,0,n,q[i].r));
    	}
    	for(int i=1;i<=m;i++) if(*q[i].ch=='a') printf("%d\n",rs[i]);
    	return 0;
    }
    
  • 相关阅读:
    CDQZ Day5
    CDQZ Day4
    CDQZ Day3
    POJ 2226 Muddy Fields
    【其他】【生成图片】【1】通过phantomjs 进行页面截图
    【Redis】【1】一些报错处理
    【Java】【15】判断url对应的图片是否存在
    【HTML&CSS】【3】点击直接发送邮件
    【微信公众号开发】【16】遇到的问题
    【Oracle】【9】取前N条记录——rownum和row_number() over()的使用
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15220269.html
Copyright © 2011-2022 走看看