FCS省选模拟赛 Day4

传送门

Solution


Code 

/*
	斯坦纳树;O(n*3^n+kE*2^n) 暂且把O(k*E)当成是spfa的复杂度
	15:15~16:20 原题:bzoj_4774 
*/
#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x*f;
}
const int MN=105,MM=1005,inf=0x3f3f3f3f;
int n,m,k;
struct edge{int to,w,nex;}e[MM<<1];int hr[MN],en;
inline void ins(int f,int t,int w)
{
	e[++en]=(edge){t,w,hr[f]};hr[f]=en;
	e[++en]=(edge){f,w,hr[t]};hr[t]=en;
}
std::queue<int> q;
int f[1<<11][MN],g[1<<11],refer[1<<6],ans=inf;
bool inq[MN];
void spfa(int *d)
{
	register int u,i;
	while(!q.empty())
	{
		u=q.front();q.pop();inq[u]=false;
		for(i=hr[u];i;i=e[i].nex)
			if(d[e[i].to]>d[u]+e[i].w)
			{
				d[e[i].to]=d[u]+e[i].w;
				if(!inq[e[i].to]) q.push(e[i].to),inq[e[i].to]=true;
			}
	}
}
int main()
{
	register int i,j,x,y,S,SS,SSS,s;
	n=read();m=read();k=read();SS=1<<k;SSS=1<<(k>>1);
	while(m--)x=read(),y=read(),ins(x,y,read());
	memset(f,0x3f,sizeof f);
	for(i=1;i<=k;++i) f[1<<i-1][i]=0;
	for(S=1;S<SS;++S)
	{
		for(i=1;i<=n;++i)
		{
			for(s=S&(S-1);s;s=(s-1)&S) f[S][i]=min(f[S][i],f[s][i]+f[S^s][i]);
			if(f[S][i]<inf) q.push(i);
		}
		spfa(f[S]);g[S]=inf;
		for(i=1;i<=n;++i) g[S]=min(g[S],f[S][i]);
	}
	for(i=0;i<SSS;++i)
	{
		s=0;
		for(j=0;j<k/2;++j) if(i>>j&1) s|=1<<(j*2);
		refer[i]=s|(s<<1);
	}
	for(S=1;S<SSS;++S)for(s=S&(S-1);s;s=(s-1)&S)
		g[refer[S]]=min(g[refer[S]],g[refer[s]]+g[refer[S^s]]);
	printf("%d
",g[SS-1]);
	return 0;
}

#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    return x*f;
}
#define int ll
const int MN=1e5+5;
int N,A[MN],w[MN],L[MN],R[MN],M;
int K[MN][350],Ll[350],Rr[350],bl,bel[MN];
int t[MN];
ll qz_a_1[350],qz_a_2[MN],sum_f[350];
void C(int x,int y){for(;x<=N;x+=(x&-x))t[x]+=y;}
int G(int x){int r=0;for(;x;x-=(x&-x))r+=t[x];return r;}

struct edge{int to,nex;}e[MN<<1];int hr[MN],en,ind;
inline void Ins(int f,int t){e[++en]=(edge){t,hr[f]};hr[f]=en;}
inline void ins(int f,int t){Ins(f,t);Ins(t,f);}
inline void dfs(int x,int f)
{
    register int i;L[x]=++ind;A[ind]=w[x];
    for(i=hr[x];i;i=e[i].nex)if(e[i].to^f)dfs(e[i].to,x);
    R[x]=ind;
}
signed main()
{
    register int i,j,Q,opt,x,y,rt;
    N=read();M=(int)((double)sqrt(N)+.5);Q=read();
    for(i=1;i<=N;++i) w[i]=read();
    for(i=1;i<=N;++i)
    {
        x=read();y=read();
        if(!x) rt=y;
        ins(x,y);
    }
    dfs(rt,0);
    for(bl=0,i=1;i<=N;++i)
    {
        C(L[i],1),C(R[i]+1,-1);
        if(i==N||i%M==0)
        {
            ++bl;Rr[bl]=i;
            for(j=1;j<=N;++j) K[j][bl]=G(j);
            for(Ll[bl]=j=(bl-1)*M+1;j<=i;++j) bel[j]=bl,C(L[j],-1),C(R[j]+1,1);
        }
    }
    for(i=1;i<=N;++i) qz_a_2[i]=qz_a_2[i-1]+A[i];
    for(i=1;i<=bl;++i) qz_a_1[i]=qz_a_2[Rr[i]];
    for(i=1;i<=N;++i) qz_a_2[i]-=qz_a_1[bel[i]-1];
    #define cal(x) (qz_a_1[bel[x]-1]+qz_a_2[x])
    for(i=1;i<=bl;++i)for(j=Ll[i];j<=Rr[i];++j)sum_f[i]+=cal(R[j])-cal(L[j]-1);
    while(Q--)
    {
        opt=read(),x=read(),y=read();
        if(opt==1)
        {
            x=L[x];y-=A[x];
            for(i=bel[x];i<=bl;++i) qz_a_1[i]+=y;
            for(i=x;i<=Rr[bel[x]];++i) qz_a_2[i]+=y;
            for(i=1;i<=bl;++i) sum_f[i]+=1ll*y*K[x][i];
            A[x]+=y;
        }
        if(opt==2)
        {
            ll ans=0;
            if(bel[x]==bel[y]) for(i=x;i<=y;++i) ans+=cal(R[i])-cal(L[i]-1);
            else
            {
                for(i=bel[x]+1;i<=bel[y]-1;++i) ans+=sum_f[i];
                for(i=x;i<=Rr[bel[x]];++i) ans+=cal(R[i])-cal(L[i]-1);
                for(i=Ll[bel[y]];i<=y;++i) ans+=cal(R[i])-cal(L[i]-1);
            }
            printf("%lld
",ans);
        }   
    }
    #undef cal
    return 0;
}

/*
	每条边都有一个存在时间[l,r],每个询问相当于求一个时刻的答案
	可以用线段树分治来维护
	要支持操作是可逆的,所以采用按秩合并的dsu
	2019/3/21 by pac 
*/
#include<bits/stdc++.h>
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
	return x*f;
}
#define reg register
const int MN=7e4+5;
int N,M,ans[MN];
std::vector<int>id[MN];
struct edge{int u,v,nex,l,r;}e[MN<<1];int en,hr[MN];
void ins(int f,int t,int l,int r)
{
	e[++en]=(edge){f,t,hr[f],l,r};hr[f]=en;
	e[++en]=(edge){t,f,hr[t],l,r};hr[t]=en;
}
class LCA
{
	int siz[MN],fa[MN],mx[MN],top[MN],dep[MN];
	void dfs1(int x,int f)
	{
		dep[x]=dep[f]+1;fa[x]=f;siz[x]=1;reg int i;
		for(i=hr[x];i;i=e[i].nex)if(e[i].v^f)
			dfs1(e[i].v,x),siz[x]+=siz[e[i].v],siz[e[i].v]>siz[mx[x]]?mx[x]=e[i].v:0;
	}
	void dfs2(int x,int f,int tp)
	{
		top[x]=tp;if(mx[x])dfs2(mx[x],x,tp);reg int i;
		for(i=hr[x];i;i=e[i].nex)if((e[i].v^f)&&(e[i].v^mx[x]))
			dfs2(e[i].v,x,e[i].v);
	}
	public:
		void init(){dfs1(1,0);dfs2(1,0,1);}
		int dis(int x,int y)
		{
			if(!x||!y) return 0;
			int r=dep[x]+dep[y];
			for(;top[x]^top[y];) dep[top[x]]>dep[top[y]]?x=fa[top[x]]:y=fa[top[y]];
			return r-2ll*min(dep[x],dep[y]);
		}
}T;
struct Ans
{
	int dl,dr,len;
	Ans Max(const Ans &o,const Ans &oo){return o.len>oo.len?o:oo;}
	Ans operator *(const Ans &o)
	{
		Ans r=Max(*this,o);
		r=Max(r,(Ans){dl,o.dl,T.dis(dl,o.dl)});
		r=Max(r,(Ans){dl,o.dr,T.dis(dl,o.dr)});
		r=Max(r,(Ans){dr,o.dl,T.dis(dr,o.dl)});
		r=Max(r,(Ans){dr,o.dr,T.dis(dr,o.dr)});
		return r;
	}
};
class DSU
{
	Ans bl[MN],st_ori[MN];
	int fa[MN],siz[MN],tp,st_l[MN],st_r[MN],ans;
	int getf(int x){return x==fa[x]?x:getf(fa[x]);}
	public:
		void init()
		{
			tp=0;ans=0;reg int i;
			for(i=1;i<=N;++i) fa[i]=i,siz[i]=1,bl[i]=(Ans){i,i,0};
		}
		void union_(int x,int y)
		{
			//if(getf(x)==19&&getf(y)==4) printf("%d %d
",x,y);
			x=getf(x);y=getf(y);
			//printf("combine %d %d
",x,y);
			if(x==y) return;
			if(siz[x]<siz[y]) std::swap(x,y);
			siz[x]+=siz[y];st_l[++tp]=x;st_r[tp]=y;
			fa[y]=x;st_ori[tp]=bl[x];bl[x]=bl[x]*bl[y];
			ans=max(ans,bl[x].len);
			//if(x==19&&bl[x].len==3) printf("find %d %d
",y,bl[y].len);
		}
		void getori(int to,int p)
		{
			reg int l,r;
			for(;tp>to;--tp)
			{
				l=st_l[tp],r=st_r[tp];
			//	printf("break %d %d
",l,r);
				siz[l]-=siz[r];fa[r]=r;
				bl[l]=st_ori[tp];
			}
			ans=p;
		}
		int Tp(){return tp;}
		int ANs(){return ans;}
	//	void print()
	//	{
	//		printf("Ans=%d
",ans);
	//		for(int i=1;i<=20;++i) printf("%d: %d
",i,bl[i].len);
	//	}
}dsu;
std::vector<int> T_ed[MN<<2];
void Md(int k,int l,int r,int a,int b)
{
	if(l==a&&r==b){T_ed[k].push_back(en);return;}
	int mid=(l+r)>>1;
	if(b<=mid) Md(k<<1,l,mid,a,b);
	else if(a>mid) Md(k<<1|1,mid+1,r,a,b);
	else Md(k<<1,l,mid,a,mid),Md(k<<1|1,mid+1,r,mid+1,b);
}
void Solve(int x,int l,int r)
{
	reg int pre=dsu.Tp(),i,res=dsu.ANs();
	for(i=T_ed[x].size()-1;~i;--i){dsu.union_(e[T_ed[x][i]].u,e[T_ed[x][i]].v);}
	if(l==r)
	{
	//	if(l==15) dsu.print();
		for(i=id[l].size()-1;~i;--i) ans[id[l][i]]=dsu.ANs();
	}
	if(l!=r)
	{
		reg int mid=(l+r)>>1;
		Solve(x<<1,l,mid);Solve(x<<1|1,mid+1,r);
	}
	dsu.getori(pre,res);
}
int main()
{
//	freopen("racing1.in","r",stdin);
//	freopen("racing1.out","w",stdout);
	N=read();M=read();
	register int i,x,y,l,r;
	for(i=1;i<N;++i)
	{
		x=read(),y=read();l=read(),r=read();
		ins(x,y,l,r);Md(1,1,N,l,r);
	//	printf("%d %d %d %d
",x,y,l,e[en].r);
	}
	for(i=1;i<=M;++i) id[read()].push_back(i);
	T.init();dsu.init();Solve(1,1,N);
	for(i=1;i<=M;++i) printf("%d
",ans[i]);
}


Blog来自PaperCloud,未经允许,请勿转载,TKS!

原文地址:https://www.cnblogs.com/PaperCloud/p/fcs_noi2019_day4.html