zoukankan      html  css  js  c++  java
  • 联合省选2021 D1T3与D2T1

    我写一下我考场上的做法吧,也算是退役前留下的最后一点点东西了。

    听说D2T1有(O(n))做法,orz

    D1T3

    首先容易发现,对于一张图(G),对(f(u,G))有贡献的({v}),是存在一条从(u)(v)的路径上的点均不小于(v),且存在一条从(v)(u)的路径上的点均不小于(v)

    以上对应于原图与反图,保留不小于(v)的点后,(v)均能走到的点数。

    总共有(O(m))张图,对于每个(v),可以(O(m))求一遍,这样暴力的复杂度为(O(m^2n)),我考场上写的这个暴力对拍跑大样例是(0.4ssim 0.5s)的((n=100,m=1000)),估计能拿(44)

    对于每张图,是没必要都求一遍的:
    枚举点(v),可以动态加入边(从最后一条边加起),当走过一个点后,就把这个点的出边全删掉,记录每个点最早能被(v)遍历到的时间。

    这样是(O(nm+n^2))的,具体可以看看我下面的代码

    #include<bits/stdc++.h>
    typedef int LL;
    #define pb push_back
    #define opt operator
    #define pii std::pair<LL,LL>
    const LL maxn=2e5+9,mod=998244353,G=3;
    LL Read(){
    	LL x(0),f(1); char c=getchar();
    	while(c<'0' || c>'9'){
    		if(c=='-') f=-1; c=getchar();
    	}
    	while(c>='0' && c<='9'){
    		x=(x<<3ll)+(x<<1ll)+c-'0'; c=getchar();
    	}
    	return x*f;
    }
    void Chkmax(LL &x,LL y){
    	x=y>x?y:x;
    }
    void Chkmin(LL &x,LL y){
    	x=y<x?y:x;
    }
    LL add(LL x,LL y){
    	x+=y;
    	return x>=mod?x-mod:x;
    }
    LL dec(LL x,LL y){
    	x-=y;
    	return x<0?x+mod:x;
    }
    LL mul(LL x,LL y){
    	return 1ll*x*y%mod;
    }
    LL Pow(LL base,LL b){
    	LL ret(1);
    	while(b){
    		if(b&1) ret=mul(ret,base);
    		base=mul(base,base); b>>=1;
    	}
    	return ret;
    }
    struct Edge{
    	LL x,y;
    }e[maxn];
    LL n,m;
    namespace sub2{
    	LL mark1[maxn],mark2[maxn];
    	std::vector<LL> V1[maxn],V2[maxn],Q[maxn];
    	void Bfs1(LL s,LL ti){
    		std::queue<LL> que; que.push(s);
    		mark1[s]=ti;
    		while(que.size()){
    			LL u(que.front()); que.pop();
    			for(LL i=0;i<V1[u].size();++i){
    				LL v(V1[u][i]); if(mark1[v]) continue;
    				mark1[v]=ti;
    				que.push(v); //mark1[v]=1;
    			}
    			std::vector<LL>().swap(V1[u]);
    		}
    	}
    	void Bfs2(LL s,LL ti){
    		std::queue<LL> que; que.push(s);
    		mark2[s]=ti;
    		while(que.size()){
    			LL u(que.front()); que.pop();
    			for(LL i=0;i<V2[u].size();++i){
    				LL v(V2[u][i]); if(mark2[v]) continue;
    				mark2[v]=ti;
    				que.push(v); //mark1[v]=1;
    			}
    			std::vector<LL>().swap(V2[u]);
    		}
    	}
    	void Solve(){
    		static LL cf[maxn];
    		for(LL i=1;i<=n;++i){
    			for(LL j=1;j<=n;++j) mark1[j]=mark2[j]=0;
    			for(LL j=1;j<=n;++j){
    				std::vector<LL>().swap(V1[j]);
    				std::vector<LL>().swap(V2[j]);
    			}
    			mark1[i]=m+1;
    			mark2[i]=m+1;
    			for(LL j=m;j>=1;--j){
    				LL x(e[j].x),y(e[j].y);
    				if(x>=i && y>=i){
    					if(mark1[x] && !mark1[y]){
    						Bfs1(y,j);
    					}else if(!mark1[x] && !mark1[y]){
    						V1[x].pb(y);
    					}
    					std::swap(x,y);
    					if(mark2[x] && !mark2[y]){
    						Bfs2(y,j);
    					}else if(!mark2[x] && !mark2[y]){
    						V2[x].pb(y);
    					}
    				}
    			}
    			for(LL j=i+1;j<=n;++j) if(mark1[j] && mark2[j]){
    				LL z(std::min(mark1[j],mark2[j]));
    				cf[z-1]++;
    			}
    		}
    		for(LL i=m;i>=0;--i) cf[i]+=cf[i+1];
    		for(LL i=0;i<=m;++i) printf("%d ",cf[i]+n); puts("");
    	}
    }
    int main(){
    	//if(system("diff x.txt "))
    	//return 0;
    //	freopen("graph.in","r",stdin);
    //	freopen("graph.out","w",stdout);
    	double ret1(clock());
    	n=Read(); m=Read();
    	for(LL i=1;i<=m;++i){
    		LL x(Read()),y(Read());
    		e[i]=(Edge){x,y};
    	}
    	sub2::Solve();
    	return 0;
    	//printf("%.10lf
    ",(clock()-ret1)/CLOCKS_PER_SEC);
    }
    

    D2T1

    我看了下其他人的代码,说一下,我下面写的特别麻烦,谨慎观看...

    这题关键在于,(p_i)均不相同,那么就说明,如果我们知道走到(u)这个位置并且吃掉了,那么现在的状态就已知了。

    考虑链的部分分,是可以(O(nlogn))倍增预处理(细节较多不说了)

    再考虑树,对树重链剖分,对于(x)往上走到某个祖先节点的贡献,同链
    对于(x)往下走到某个子树节点,可以在重链上走,重链上同链那样预处理,总复杂度(O(nlogn+qlog^2n))

    #include<bits/stdc++.h>
    typedef int LL;
    #define pb push_back
    #define opt operator
    #define pii std::pair<LL,LL>
    const LL maxn=2e5+9,mod=998244353,G=3;
    LL Read(){
    	LL x(0),f(1); char c=getchar();
    	while(c<'0' || c>'9'){
    		if(c=='-') f=-1; c=getchar();
    	}
    	while(c>='0' && c<='9'){
    		x=(x<<3ll)+(x<<1ll)+c-'0'; c=getchar();
    	}return x*f;
    }
    LL add(LL x,LL y){
    	x+=y;
    	return x>=mod?x-mod:x;
    }
    LL dec(LL x,LL y){
    	x-=y;
    	return x<0?x+mod:x;
    }
    LL mul(LL x,LL y){
    	return 1ll*x*y%mod;
    }
    LL Pow(LL base,LL b){
    	LL ret(1); while(b){
    		if(b&1) ret=mul(ret,base);
    		base=mul(base,base); b>>=1;
    	}return ret;
    }
    LL m;
    LL root[maxn];
    namespace Sgt{
    	LL nod;
    	LL son[maxn*30][2],a[maxn*30];
    	void Modify(LL &nw,LL pre,LL l,LL r,LL x,LL v){
    		nw=++nod;
    		son[nw][0]=son[pre][0]; son[nw][1]=son[pre][1];
    		if(l==r){
    			a[nw]=v; return;
    		}
    		LL mid(l+r>>1);
    		if(x<=mid) Modify(son[nw][0],son[pre][0],l,mid,x,v);
    		else Modify(son[nw][1],son[pre][1],mid+1,r,x,v);
    	}
    	LL Query(LL nw,LL l,LL r,LL x){
    		if(l==r) return a[nw];
    		LL mid(l+r>>1);
    		if(x<=mid) return Query(son[nw][0],l,mid,x);
    		else return Query(son[nw][1],mid+1,r,x);
    	}
    	LL Find(LL u,LL c){
    		return Query(root[u],1,m,c);
    	}
    }
    LL n,C,q;
    LL fa[maxn],dep[maxn],p[maxn],w[maxn],pos[maxn],gf[maxn],son[maxn],top[maxn],istop[maxn];
    LL size[maxn];
    //gf: top first p[1]
    LL lp1[maxn][20],lp2[maxn][20],dp1[maxn][20],dp2[maxn][20],inc[maxn][20];
    std::vector<LL> V[maxn],col[maxn];
    void Init(){
    	n=Read(); m=Read(); C=Read();
    	for(LL i=1;i<=C;++i){
    		p[i]=Read();
    	}
    	for(LL i=1;i<=C;++i){
    		pos[p[i]]=i;
    	}
    	for(LL i=1;i<=n;++i) w[i]=Read();
    	for(LL i=1;i<n;++i){
    		LL x(Read()),y(Read());
    		V[x].pb(y); V[y].pb(x);
    	}
    }
    void Dfs1(LL u,LL f){
    	dep[u]=dep[f]+1; fa[u]=f;
    	LL x(pos[w[u]]);
    	if(x){
    		LL y(p[x+1]);
    		//printf("# %d: %d %d
    ",u,x,y);
    		y=(col[y].size()?col[y].back():0);
    		//printf("%d
    ",y);
    		for(LL i=0;i<=19;++i) dp2[u][i]=dp1[y][i];
    		dp1[u][0]=u;
    		//dp2[u][0]=y;
    		for(LL i=1;i<=19;++i){
    			LL v(dp1[u][i-1]);
    			dp1[u][i]=dp2[v][i-1];
    		}
    		//for(LL i=0;i<=3;++i) printf("%d ",dp1[u][i]); puts("");
    		//for(LL i=0;i<=3;++i) printf("%d ",dp2[u][i]);
    		//puts(""); puts("");
    	}
    	inc[u][0]=f;
    	for(LL i=1;i<=19;++i){
    		inc[u][i]=inc[inc[u][i-1]][i-1];
    	}
    	col[w[u]].pb(u);
    	gf[u]=col[p[1]].size()?col[p[1]].back():0;
    	size[u]=1; son[u]=0;
    	for(LL i=0;i<V[u].size();++i){
    		LL v(V[u][i]); if(v==f) continue;
    		Dfs1(v,u); size[u]+=size[v];
    		if(size[v]>size[son[u]]) son[u]=v;
    	}
    	col[w[u]].pop_back();
    }
    void Dfs2(LL u,LL f,LL ff){
    	istop[son[u]]=0; top[u]=ff;
    	if(son[u]){
    		Dfs2(son[u],u,ff);
    	}
    	for(LL i=0;i<V[u].size();++i){
    		LL v(V[u][i]); if(v==f || v==son[u]) continue;
    		Dfs2(v,u,v);
    	}
    }
    void Build2(){//weight lian
        Sgt::nod=0;
        for(LL i=1;i<=m;++i) std::vector<LL>().swap(col[i]);
        std::vector<LL> suq;
    	for(LL tp=1;tp<=n;++tp) if(istop[tp]){
    		std::vector<LL> ().swap(suq);
    		LL u(tp);
    		while(u){
    			suq.pb(u); u=son[u];
    		}
    		LL sz(suq.size()-1); suq.pb(0);
    		//for(LL i=sz;i>=0;--i) printf("%d ",suq[i]); puts("");
    		for(LL i=sz;i>=0;--i){
    			u=suq[i];
    			Sgt::Modify(root[suq[i]],root[suq[i+1]],1,m,w[u],u);
    		}
    		for(LL i=sz;i>=0;--i){
    			u=suq[i];
    			LL x(pos[w[u]]);
    			if(x){
    				LL y(p[x+1]);
    				//printf("# (%d)%d,%d
    ",u,x,y);
    				y=(col[y].size()?col[y].back():0);
    				//printf("%d
    ",y);
    				for(LL j=0;j<=19;++j) lp2[u][j]=lp1[y][j];
    				lp1[u][0]=u;
    				for(LL j=1;j<=19;++j){
    					LL v(lp1[u][j-1]);
    					lp1[u][j]=lp2[v][j-1];
    				}
    				//for(LL j=0;j<=3;++j) printf("%d ",lp1[u][j]); puts("");
    				//for(LL j=0;j<=3;++j) printf("%d ",lp2[u][j]); puts("");
    			}
    			col[w[u]].pb(u);
    		}
            for(LL i=0;i<=sz;++i) std::vector<LL>().swap(col[w[suq[i]]]);
    	}
    }
    void Build(){
    	Dfs1(1,0);
    	//puts("----------------------");
    	for(LL i=1;i<=n;++i) istop[i]=1;
    	Dfs2(1,0,1);
    	Build2();
    	//puts("-----------------------");
    	/*for(LL i=1;i<=n;++i){
    		Dfs3()
    	}*/
    }
    LL Lca(LL x,LL y){
    	if(dep[x]<dep[y]) std::swap(x,y);
    	for(LL i=19;i>=0;--i) if(dep[inc[x][i]]>=dep[y]) x=inc[x][i];
    	if(x==y) return x;
    	for(LL i=19;i>=0;--i) if(inc[x][i]!=inc[y][i]){
    		x=inc[x][i]; y=inc[y][i];
    	}return inc[x][0];
    }
    pii Search1(LL x,LL y){//not in one   first:down second:son
        
    	while(true){
    		y=top[y];
    		if(top[fa[y]]==top[x]) return pii(fa[y],y);
    		y=fa[y];
    	}
    }
    LL Search2(LL x,LL c){//x lian find c
    	return Sgt::Find(x,c);
    }
    LL Solve(LL x,LL y){
    	LL lca(Lca(x,y));
    	//printf("(%d,%d)%d
    ",x,y,lca);
    	LL len(1);
    	{
    		LL u(gf[x]);
    		//printf("# %d
    ",u);
    	    if(u){
    			if(dep[u]<dep[lca]){
    				x=lca;
    			}else{
    				x=u;
    				//for(LL i=0;i<=2;++i) printf("%d ",dp2[x][i]); puts("");
    				for(LL i=19;i>=0;--i) if(dep[dp2[x][i]]>=dep[lca]){
    					len+=(1<<i); x=dp2[x][i];
    				}
    				++len; x=lca;
    			}
    	    }else{
    		    x=lca;
    	    }
    	}
    	if(len>C) return C;
    	//printf("%d: %d,%d
    ",len,x,y);
    	while(top[x]!=top[y]){
    		LL z(Search2(x,p[len]));
    		//puts("#");
    		pii tmp(Search1(x,y));
    		//printf("%d (%d,%d)
    ",z,tmp.first,tmp.second);
    		if(!z || dep[z]>dep[tmp.first]){
    			x=tmp.second;
    		}else{
    			x=z; //if(len>C) return C;
    			for(LL i=19;i>=0;--i) if(lp2[x][i] && dep[lp2[x][i]]<=dep[tmp.first]){
    				len+=(1<<i); x=lp2[x][i];
    			}
    			++len; x=tmp.second;
    			if(len>C) return C;
    		}
    	}
    	if(top[x]==top[y]){
    		LL z(Search2(x,p[len]));
    		//printf("# (%d)%d:%d
    ",x,z,p[len]);
    		if(!z || dep[z]>dep[y]){
    			return len-1;
    		}
    		x=z;
    		//printf("# %d
    ",z);
    		//for(LL i=0;i<=3;++i) printf("%d ",lp2[x][i]); puts("");
    		for(LL i=19;i>=0;--i) if(lp2[x][i] && dep[lp2[x][i]]<=dep[y]){
    			len+=(1<<i); x=lp2[x][i];
    		}
    		++len;
    		assert(len<=C+1);
    		return len-1;
    	}
    	assert(0);
    }
    void Solve(){
    	q=Read();
    	while(q--){
    		LL x(Read()),y(Read());
    		LL ret=Solve(x,y);
    		printf("%d
    ",ret);
    	}
    }
    int main(){
    	/*
    	if(system("diff x.txt gem3.ans")) return 0;
    	else puts("Ac");
    	return 0;
    //	*/
    	//freopen("y1.txt","r",stdin);
    //	freopen("gem.in","r",stdin);
    	//double ret1(clock());
    	//freopen("x.txt","w",stdout);
    //	freopen("gem.out","w",stdout);
     	Init();
    	//puts("-----------------");
    	Build();
    	//puts("-----------------");
    	Solve();
    	//printf("%.10lf
    ",(clock()-ret1)/CLOCKS_PER_SEC);
    	return 0;
    }
    
  • 相关阅读:
    《3S新闻周刊》No.8:导航迈入井喷时代
    ESRI的Blog正式开始更新
    Google Earth中国部分数据重大更新
    说说EverNote
    选择ESRI的理由
    使用XAML和SharpMap渲染一幅地图
    《Excel与VBA程序设计》最新消息,预计9月上市
    基于Flash的全球卫星照片在线服务
    javascript运算符重载的实现
    uml各类图
  • 原文地址:https://www.cnblogs.com/Grice/p/14645327.html
Copyright © 2011-2022 走看看