3 条题解

  • 0
    @ 2026-1-18 23:50:35

    这是另一个时间复杂度较高的做法:将询问离线下来,利用莫队和可撤销并查集完成操作。

    #include<bits/stdc++.h>
    #define rep(i,a,b) for(int i(a);i<=(b);++i)
    #define req(i,a,b) for(int i(a);i>=(b);--i)
    using namespace std;
    char buf[1<<23],*p1=buf,*p2=buf,ubuf[1<<23],*u=ubuf;
    #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
    template<typename TP> inline TP read(TP &num)
    {
    	TP x=0;
    	int f=0;
    	char ch=getchar();
    	while(ch<48||ch>57) f|=ch=='-',ch=getchar();
    	while(48<=ch&&ch<=57) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
    	return num=f?-x:x;
    }
    template<typename ...Args> inline void read(Args &...args)
    {
    	(read(args),...);
    }
    template<typename TP> inline void write(TP x)
    {
    	(x<0)?(putchar('-'),x=-x):0;
    	(x>9)?(write(x/10),0):0;
    	putchar((x%10)^48);
    }
    template<typename TP> inline void writeln(TP x)
    {
    	write<TP>(x);
    	puts("");
    }
    struct DSU
    {
    	int n,st,sts;
    	vector<int> dsu;
    	stack<pair<int,int>> undo;
    	DSU(int n)
    	{
    		this->n=n;
    		dsu.resize(n+1);
    		rep(i,0,n) dsu[i]=i;
    		st=n;
    	}
    	int find(int x,bool sa=0)
    	{
    		if(dsu[x]==x) return x;
    		if(sa) undo.emplace(x,dsu[x]);
    		return dsu[x]=find(dsu[x],sa);
    	}
    	bool join(int x,int y)
    	{
    		int fx=find(x),fy=find(y);
    		if(fx==fy) return 0;
    		--st;
    		dsu[fx]=fy;
    		return 1;
    	}
    	void save(){sts=st;}
    	void recover()
    	{
    		st=sts;
    		while(!undo.empty())
    		{
    			pair<int,int> tmp=undo.top();undo.pop();
    			dsu[tmp.first]=tmp.second;
    		}
    	}
    	void tempjoin(int x,int y)
    	{
    		int fx=find(x,1),fy=find(y,1);
    		if(fx==fy) return;
    		--st;
    		undo.emplace(fx,dsu[fx]);
    		dsu[fx]=fy;
    	}
    };
    namespace Solve
    {
    	int n,m,q,block=170;
    	inline void main()
    	{
    		read(n,m,q);
    		vector<array<int,2>> edge(m);
        	vector<array<int,3>> query(q);
    		rep(i,0,m-1) read(edge[i][0],edge[i][1]);
    		rep(i,0,q-1) read(query[i][0],query[i][1]),--query[i][0],--query[i][1],query[i][2]=i;
    		sort(query.begin(),query.end(),[](array<int,3> &a,array<int,3> &b)
    		{
    			int ba=a[0]/block,bb=b[0]/block;
            	if(ba!=bb) return ba<bb;
            	return a[1]<b[1];
        	});
        	DSU dsu(n);
        	vector<int> ans(q);
        	int lst=-1,pos=0;
        	rep(i,0,q-1)
    		{
    			int cur=query[i][0]/block;
    			if(cur!=lst)
    			{
    				dsu=DSU(n);
    				lst=cur;
    				pos=(cur+1)*block-1;
    				rep(j,(cur+1)*block,query[i][1]) dsu.join(edge[j][0],edge[j][1]),++pos;
    			}
    			while(pos<query[i][1]) ++pos,dsu.join(edge[pos][0],edge[pos][1]);
    			dsu.save();
    	        for(int j=query[i][0];j<=query[i][1]&&j<(cur+1)*block;++j) dsu.tempjoin(edge[j][0],edge[j][1]);
    	        ans[query[i][2]]=dsu.st;
    	        dsu.recover();
    		}
    		rep(i,0,q-1) writeln(ans[i]);
    	}
    }
    signed main()
    {
    	int T=1;while(T--)Solve::main();
        return 0;
    }
    

    信息

    ID
    134
    时间
    100ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    37
    已通过
    4
    上传者