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;
    }
    
  • 相关阅读:
    LeetCode 121. Best Time to Buy and Sell Stock
    LeetCode 221. Maximal Square
    LeetCode 152. Maximum Product Subarray
    LeetCode 53. Maximum Subarray
    LeetCode 91. Decode Ways
    LeetCode 64. Minimum Path Sum
    LeetCode 264. Ugly Number II
    LeetCode 263. Ugly Number
    LeetCode 50. Pow(x, n)
    LeetCode 279. Perfect Squares
  • 原文地址:https://www.cnblogs.com/Grice/p/14645327.html
Copyright © 2011-2022 走看看