• [BZOJ1018][SHOI2008]堵塞的交通traffic 时间分治线段树


    题面

    介绍一种比较慢的但是好想的做法。

    网上漫天的线段树维护联通性,然后想起来费很大周折也很麻烦。我的做法也是要用线段树的,不过用法完全不同。

    这个东西叫做时间分治线段树。

    首先我们建一个(1..m+1)的线段树。

    很好做出每条边的存在时间的区间是吧,所以我们这段时间存入线段树中。(最后都没有消失的视为(m+1)时间消失)记录下每个节点的对应区间的所有边。

    然后从上往下扫整个线段树,将该段区间的边用并查集维护连通性。遇到询问就查一下。

    回去的时候还有撤掉之前连的边,所以并查集给用只有按秩合并,不带按秩合并。这样并查集一次的操作时间复杂度(O(log n))

    总时间复杂度(O(nlog ^2 n))

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<vector>
    #include<map>
    #define lc o<<1
    #define rc o<<1|1
    #define REP(i,a,n) for(register int i(a);i<=(n);++i)
    #define PER(i,a,n) for(register int i(a);i>=(n);--i)
    #define FEC(i,x,y) for(register int i=head[x],y=g[i].to;i;i=g[i].ne,y=g[i].to)
    #define dbg(...) fprintf(stderr,__VA_ARGS__)
    const int SZ=(1<<21)+1;char ibuf[SZ],*iS,*iT,obuf[SZ+128],*oS=obuf,*oT=obuf+SZ-1;
    #ifdef ONLINE_JUDGE
    #define gc() (iS==iT?(iT=(iS=ibuf)+fread(ibuf,1,SZ,stdin),(iS==iT?EOF:*iS++)):*iS++)
    #else
    #define gc() getchar()
    #endif
    template<typename I>inline void read(I&x){char c=gc();int f=0;for(;c<'0'||c>'9';c=gc())c=='-'?f=1:0;for(x=0;c>='0'&&c<='9';c=gc())x=(x<<1)+(x<<3)+(c&15);f?x=-x:0;}
    template<typename I>inline void read(I*s){char c=gc();for(;c<=' ';c=gc());for(;c>' ';c=gc())*s++=c;*s='';}
    inline void flush(){fwrite(obuf,1,oS-obuf,stdout);oS=obuf;}
    #define printf(...) (oS>oT&&(flush(),1),oS+=sprintf(oS,__VA_ARGS__))
    #define putchar(x) (oS>oT&&(flush(),1),*oS++=(x))
    template<typename A,typename B>inline char SMAX(A&a,const B&b){return a<b?a=b,1:0;}
    template<typename A,typename B>inline char SMIN(A&a,const B&b){return a>b?a=b,1:0;}
    typedef long long ll;typedef unsigned long long ull;typedef std::pair<int,int>pii;
    
    const int N=200000+7;
    int n,m,x1,y1,x2,y2,id[3][N],ans[N],ext[N];char opt[7];
    
    int fa[N],siz[N];
    inline int Find(int x){return fa[x]==x?x:Find(fa[x]);}
    inline void Union(int x,int y){x=Find(x),y=Find(y);if(siz[x]<siz[y])std::swap(x,y);SMAX(siz[x],siz[y]+1);fa[y]=x;}
    
    struct QUE{int opt,x,y,prex,prey,sizx,sizy;}q[N<<1];std::vector<QUE>t[N<<1];
    inline void Insert(int o,int L,int R,int l,int r,QUE k){
    	if(l<=L&&R<=r)return t[o].push_back(k);
    	int M=(L+R)>>1;if(l<=M)Insert(lc,L,M,l,r,k);if(r>M)Insert(rc,M+1,R,l,r,k);
    }
    inline void Insert(int o,int L,int R,int x,QUE k){
    	if(L==R)return t[o].push_back(k);
    	int M=(L+R)>>1;x<=M?Insert(lc,L,M,x,k):Insert(rc,M+1,R,x,k);
    }
    inline void Solve(int o,int L,int R){
    	int len=t[o].size();REP(i,0,len-1)if(t[o][i].opt){const int&x=Find(t[o][i].x),y=Find(t[o][i].y);if(x==y)continue;t[o][i].prex=fa[x],t[o][i].prey=fa[y];t[o][i].sizx=siz[x],t[o][i].sizy=siz[y];Union(x,y);}
    	if(L==R){REP(i,0,len-1)if(!t[o][i].opt)ans[t[o][i].prex]=Find(t[o][i].x)==Find(t[o][i].y);}
    	else{int M=(L+R)>>1;Solve(lc,L,M);Solve(rc,M+1,R);}
    	PER(i,len-1,0)if(t[o][i].opt){const int&x=t[o][i].prex,&y=t[o][i].prey;fa[x]=x,fa[y]=y,siz[x]=t[o][i].sizx,siz[y]=t[o][i].sizy;}//错误笔记:和第44行一样,这里的prex啥的应该存下来其find的信息不是自己的信息
    }
    
    std::map<pii,int>mp;
    int main(){
    	read(n);REP(i,1,n)id[1][i]=i,id[2][i]=n+i,fa[i]=i,fa[n+i]=n+i,siz[i]=siz[n+i]=1;n<<1;//错误笔记:并查集要记得初始化
    	REP(i,1,N){
    		read(opt);if(*opt=='E'){m=i-1;break;}
    		read(x1),read(y1),read(x2),read(y2);q[i]=QUE{(int)*opt,id[x1][y1],id[x2][y2]};
    	}
    	REP(i,1,m){
    		int opt=q[i].opt,id1=q[i].x,id2=q[i].y;
    		if(opt=='O')mp[pii(id1,id2)]=i;
    		else if(opt=='C'){
    			pii e(id1,id2);
    			Insert(1,1,m+1,mp[e],i,QUE{1,id1,id2});mp.erase(e);
    		}else if(opt=='A')Insert(1,1,m+1,i,QUE{0,id1,id2,++ans[0]});
    	}
    	std::map<pii,int>::iterator p=mp.begin();
    	while(p!=mp.end()){Insert(1,1,m+1,p->second,m+1,QUE{1,p->first.first,p->first.second});++p;}
    	Solve(1,1,m+1);
    	REP(i,1,ans[0])putchar(ans[i]?'Y':'N'),putchar('
    ');
    	return flush(),0;
    }
    
  • 相关阅读:
    实现对象属性的lazy-loading(延迟加载)
    Scikit-Learn机器学习入门
    实现后门程序以及相应的rootkits,实现对后门程序的隐藏
    关于iptables命令
    基于netfilter和LVM的密码窃取
    实验一:网络嗅探器
    实验二:ICMP重定向攻击
    第八节课、第九节
    第六、七课
    python读取excel文件
  • 原文地址:https://www.cnblogs.com/hankeke/p/BZOJ1018.html
Copyright © 2020-2023  润新知