1. 程式人生 > >2001: [Hnoi2010]City 城市建設

2001: [Hnoi2010]City 城市建設

當分治到區間[l,r]時:

如果l==r,直接跑mst,結束。否則:

S1存初始邊和[1,l)的邊,S2存[l,r]的邊。

先把S2中的邊權全都改成inf,跑mst,S1中用不到的邊即為無用邊,直接刪去。

再把S2中的邊權全都改成-inf,跑mst,S1中仍被用到的邊即為必需邊,把這些邊連線的兩點用並查集搞在一起,並把這些邊權和傳到下一層。

對於分治的每一種深度,開一個邊、一個點集,一個並查集,一坨詢問。因為深度最多為logn、同種深度的區間不會同時執行,所以只需開logn個就夠了,空間是不會爆的。

TMD把題意看錯了,寫了個只有加邊的。。。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define sqr(x) ((x)*(x))
#define G getchar()
#define LL long long
#define pii pair<int,int>
#define mkp make_pair
#define X first
#define Y second
#define N 200005
#define NN 500005
#define inf 100000000
struct EDGE{int a,b,w;}qu[NN];
struct EDGE2{int a,b,w,wz;}ek[NN<<1];
struct node{
	EDGE e[NN<<1];
	int tot,poi[N],cnt,par[N],sz[N];
}Hz[17];
int n,m,Q,totk,park[N],szk[N];
LL ans[NN];
bool flg[NN<<1];
void read(int &x){
	char ch=G;
	while(ch<48||ch>57)ch=G;
	for(x=0;ch>47&&ch<58;ch=G)x=x*10+ch-48; 
}
bool cmp(EDGE2 x,EDGE2 y){return x.w<y.w;}
int getpar(int *par0,int x){
	if(par0[x]!=x)par0[x]=getpar(par0,par0[x]);
	return par0[x];
}
void cmb(int *par0,int *sz0,int x,int y){
	x=getpar(par0,x);y=getpar(par0,y);
	if(sz0[x]<sz0[y])par0[x]=par0[y];
	else par0[y]=par0[x];
}
LL kruscal(int *poi0,int cnt0){
	int i,x,y,j;LL rtn=0;
	rep(i,1,cnt0)szk[park[i]=i]=1;
	rep(i,1,totk)flg[i]=0;
	sort(ek+1,ek+totk+1,cmp);
	for(i=j=1;j<cnt0;++i){
		x=getpar(park,ek[i].a);y=getpar(park,ek[i].b);
		if(x==y)continue;++j;
		flg[ek[i].wz]=1;rtn+=ek[i].w;
		cmb(park,szk,ek[i].a,ek[i].b);
	}
	return rtn;
}
void cdq(int l,int r,LL sum,int dep){
	EDGE *e0=Hz[dep].e;
	int &tot0=Hz[dep].tot,*poi0=Hz[dep].poi,&cnt0=Hz[dep].cnt,*par0=Hz[dep].par,*sz0=Hz[dep].sz;
	int i;
	rep(i,1,cnt0)sz0[par0[i]=i]=1;
	totk=tot0;
	rep(i,1,tot0)ek[i]=(EDGE2){e0[i].a,e0[i].b,e0[i].w,i};
	if(l==r){
		ek[++totk]=(EDGE2){qu[l].a,qu[l].b,qu[l].w,totk};
		ans[l]=kruscal(poi0,cnt0)+sum;
		return;
	}
	rep(i,l,r)ek[++totk]=(EDGE2){qu[i].a,qu[i].b,inf,totk};
	kruscal(poi0,cnt0);
	totk=tot0;
	rep(i,1,tot0){
		ek[i]=(EDGE2){e0[i].a,e0[i].b,e0[i].w,i};
		if(!flg[i])e0[i].a=0;
	}
	rep(i,l,r)ek[++totk]=(EDGE2){qu[i].a,qu[i].b,-inf,totk};
	kruscal(poi0,cnt0);
	EDGE *e1=Hz[dep+1].e;
	int &tot1=Hz[dep+1].tot,*poi1=Hz[dep+1].poi,&cnt1=Hz[dep+1].cnt;
	int x,mid=l+r>>1;
	rep(i,1,tot0){
		if(!e0[i].a)continue;
		if(flg[i]){
			cmb(par0,sz0,e0[i].a,e0[i].b);
			e0[i].a=0;sum+=e0[i].w;
		}
	}
	rep(i,1,cnt0){
		x=poi0[i];
		if(getpar(par0,x)==x)poi1[++cnt1]=x;
	}
	rep(i,1,tot0)if(e0[i].a)
		e1[++tot1]=(EDGE){getpar(par0,e0[i].a),getpar(par0,e0[i].b),e0[i].w};
	rep(i,l,r){
		qu[i].a=getpar(par0,qu[i].a);
		qu[i].b=getpar(par0,qu[i].b);
	}
	cdq(l,mid,sum,dep+1);
	rep(i,l,mid)e1[++tot1]=qu[i];
	cdq(mid+1,r,sum,dep+1);
}
int main(){
	int i,x;
	read(n);read(m);read(Q);
	EDGE *e0=Hz[1].e;
	rep(i,1,m){
		read(e0[i].a);read(e0[i].b);read(e0[i].w);
	}
	Hz[1].tot=m;
	int *poi0=Hz[1].poi;
	rep(i,1,n)poi0[i]=i;
	Hz[1].cnt=n;
	rep(i,1,Q){
		read(x);read(qu[i].w);
		qu[i].a=e0[x].a;qu[i].b=e0[x].b;
	}
	cdq(1,Q,0LL,1);
	rep(i,1,Q)printf("%d\n",ans[i]);
	return 0;
}

簡直腦子進水,下面的程式碼寫了我一整天。不過我還真沒見過這麼難寫的題。覺得這題比Claris loves painting 還難寫得多。

#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
#include<map>
#include<cmath>
#include<queue>
using namespace std;
#define rep(i,j,k) for(i=j;i<=k;++i)
#define per(i,j,k) for(i=j;i>=k;--i)
#define sqr(x) ((x)*(x))
#define G getchar()
#define LL long long
#define pii pair<int,int>
#define mkp make_pair
#define X first
#define Y second
#define N 20005
#define NN 50005
#define inf 100000000
struct EDGE{int a,b,w;};
struct EDGE2{int a,b,w,wz;}ek[NN<<1];
struct QUERY{int cur,w;};
struct node{
	EDGE e[NN<<1];QUERY qu[NN];
	int tot,poi[N],cnt,par[N],sz[N];
}Hz[20];
int n,m,Q,totk,park[N],szk[N],key[NN];
LL ans[NN];
bool flg[NN<<1];
void read(int &x){
	char ch=G;
	while(ch<48||ch>57)ch=G;
	for(x=0;ch>47&&ch<58;ch=G)x=x*10+ch-48; 
}
bool cmp(EDGE2 x,EDGE2 y){return x.w<y.w;}
int getpar(int *par0,int x){
	if(par0[x]!=x)par0[x]=getpar(par0,par0[x]);
	return par0[x];
}
void cmb(int *par0,int *sz0,int x,int y){
	x=getpar(par0,x);y=getpar(par0,y);
	if(sz0[x]<sz0[y])sz0[par0[x]=y]+=sz0[x];
	else sz0[par0[y]=x]+=sz0[y];
}
LL kruscal(int *poi0,int cnt0){
	int i,x,y,j;LL rtn=0;
	rep(i,1,cnt0)szk[park[poi0[i]]=poi0[i]]=1;
	rep(i,1,totk)flg[i]=0;
	sort(ek+1,ek+totk+1,cmp);
	for(i=j=1;j<cnt0;++i){
		x=getpar(park,ek[i].a);y=getpar(park,ek[i].b);
		if(x==y)continue;++j;
		flg[ek[i].wz]=1;rtn+=ek[i].w;
		cmb(park,szk,ek[i].a,ek[i].b);
	}
	return rtn;
}
void cdq(int l,int r,LL sum,int dep){
	EDGE *e0=Hz[dep].e;QUERY *qu0=Hz[dep].qu;
	int &tot0=Hz[dep].tot,*poi0=Hz[dep].poi,&cnt0=Hz[dep].cnt,*par0=Hz[dep].par,*sz0=Hz[dep].sz;
	int i;
	rep(i,1,cnt0)sz0[par0[poi0[i]]=poi0[i]]=1;
	totk=tot0;
	rep(i,1,tot0)ek[i]=(EDGE2){e0[i].a,e0[i].b,e0[i].w,i};
	if(l==r){
		ek[qu0[l].cur].w=qu0[l].w;
		ans[l]=kruscal(poi0,cnt0)+sum;
		return;
	}
	rep(i,l,r)
		ek[qu0[i].cur].w=inf;
	kruscal(poi0,cnt0);
	totk=tot0;
	rep(i,l,r)flg[qu0[i].cur]=1;
	rep(i,1,tot0){
		ek[i]=(EDGE2){e0[i].a,e0[i].b,e0[i].w,i};
		if(!flg[i])e0[i].a=0;
	}
	rep(i,l,r)ek[qu0[i].cur].w=-inf;
	kruscal(poi0,cnt0);
	EDGE *e1=Hz[dep+1].e;QUERY *qu1=Hz[dep+1].qu;
	int &tot1=Hz[dep+1].tot,*poi1=Hz[dep+1].poi,&cnt1=Hz[dep+1].cnt;
	int x,mid=l+r>>1;
	rep(i,l,r)flg[qu0[i].cur]=0;
	rep(i,1,tot0){
		if(!e0[i].a)continue;
		if(flg[i]){
			cmb(par0,sz0,e0[i].a,e0[i].b);
			e0[i].a=0;sum+=e0[i].w;
		}
	}
	cnt1=tot1=0;
	rep(i,1,cnt0){
		x=poi0[i];
		if(getpar(par0,x)==x)poi1[++cnt1]=x;
	}
	rep(i,1,tot0)if(e0[i].a)
		e1[key[i]=++tot1]=(EDGE){getpar(par0,e0[i].a),getpar(par0,e0[i].b),e0[i].w};
	rep(i,l,r)qu1[i]=(QUERY){key[qu0[i].cur],qu0[i].w};
	cdq(l,mid,sum,dep+1);
	tot1=0;
	rep(i,1,tot0)if(e0[i].a)
		e1[++tot1]=(EDGE){getpar(par0,e0[i].a),getpar(par0,e0[i].b),e0[i].w};
	rep(i,l,mid)e1[qu1[i].cur].w=qu1[i].w;
	cdq(mid+1,r,sum,dep+1);
}
int main(){
	int i;
	read(n);read(m);read(Q);
	EDGE *e0=Hz[1].e;QUERY *qu0=Hz[1].qu;
	rep(i,1,m){
		read(e0[i].a);read(e0[i].b);read(e0[i].w);
	}
	Hz[1].tot=m;
	int *poi0=Hz[1].poi;
	rep(i,1,n)poi0[i]=i;
	Hz[1].cnt=n;
	rep(i,1,Q){
		read(qu0[i].cur);read(qu0[i].w);
	}
	cdq(1,Q,0LL,1);
	rep(i,1,Q)printf("%lld\n",ans[i]);
	return 0;
}