BZOJ 2001: [Hnoi2010]City 城市建设

好鬼的CDQ分治,感觉复杂度好迷的说感觉就是个剪枝的暴力

首先看到题目,动态MST,妈妈我会线段树分治+LCT然后这题就做完了

大体上很套路,我们把修改看作一条边的删除以及一条新边的加入,就可以求出每条边出现的时间区间

然后按时间为下标建线段树,我们只要能实现插入一条边/撤销即可,然后我们发现这个东西可以很容易LCT维护,每次找出成环的路径上的最大值然后替换掉即可

总体复杂度\(O(n\log^2 n)\),据说常数巨大(我不想写),因此这里讲一种抄来的玄学CDQ分治的做法

首先我们要明确CDQ的本质:讲可以一些操作间重复的部分最大化,然后解决这个重复部分

考虑我们现在处理的区间是\([l,r]\),那么对于不被这个区间操作影响的边(姑且称为静态边),显然我们可以找出其中一些必须选的边和一些肯定不选的边,然后再往下递归的时候就不用考虑它们

那具体怎么处理呢,我们考虑进行以下操作:

  1. 将现在分治的区间内的所有边(姑且称为动态边),边权设为\(-\infty\),然后跑一遍MST,然后我们找出MST上的所有静态边(边权不为\(-\infty\)),它们显然是必选的
  2. 将现在分治的区间内的所有边,边权设为\(\infty\),然后跑一遍MST,然后我们找出没有出现在MST上的所有静态边(边权不为\(\infty\)),它们显然是无用的

然后我们把所有的必选边先连起来,然后往下处理的时候忽略掉无用边

根据某种神奇的力量(或者感性理解),这样每次处理的边数会减半(会证明的老哥麻烦告诉我下证明),因此总复杂度就是\(O(n\log^2 n)\)的,但是常数极小(分治+排序),不像某两大常数算法的结合

#include
#include
#include
#include
#define RI register int
#define CI const int&
#define Tp template 
#define pb push_back
using namespace std;
typedef long long LL;
const int N=50005,INF=1e9;
struct edge
{
	int x,y,w,id;
	friend inline bool operator < (const edge& A,const edge& B)
	{
		return A.w E[20]; int n,m,q,val[N],px[N],py[N],pos[N]; LL ans[N];
class FileInputOutput
{
	private:
		static const int S=1<<21;
		#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
		#define pc(ch) (Ftop!=Fend?*Ftop++=ch:(fwrite(Fout,1,S,stdout),*(Ftop=Fout)++=ch))
		char Fin[S],Fout[S],*A,*B,*Ftop,*Fend; int pt[25];
	public:
		inline FileInputOutput(void) { Ftop=Fout; Fend=Fout+S; }
		Tp inline void read(T& x)
		{
			x=0; char ch; while (!isdigit(ch=tc()));
			while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
		}
		Tp inline void write(T x)
		{
			RI ptop=0; while (pt[++ptop]=x%10,x/=10);
			while (ptop) pc(pt[ptop--]+48); pc('\n');
		}
		inline void flush(void)
		{
			fwrite(Fout,1,Ftop-Fout,stdout);
		}
		#undef tc
		#undef pc
}F;
class UnionFindSet
{
	private:
		int fa[N];
	public:
		inline void init(CI n,edge *e)
		{
			for (RI i=0;i>1; solve(l,mid,dep+1,sum); solve(mid+1,r,dep+1,sum);
}
int main()
{
	//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
	RI i; for (F.read(n),F.read(m),F.read(q),i=1;i<=m;++i)
	F.read(nw.x),F.read(nw.y),F.read(nw.w),val[i]=nw.w,nw.id=i,E[0].pb(nw);
	for (i=1;i<=q;++i) F.read(px[i]),F.read(py[i]);
	for (solve(),i=1;i<=q;++i) F.write(ans[i]); return F.flush(),0;
}

你可能感兴趣的:(BZOJ 2001: [Hnoi2010]City 城市建设)