博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

10.28 牛客提高集训营7


2018.10.28 牛客提高集训营7

期望得分:100+100+100
实际得分:100+100+100(0)

好不容易良心场,但是。。。

跑得快了,但是分没了。
预处理写错了,为什么上面两个还能过对拍啊==

比赛链接

A 中国式家长2(模拟)

题目链接

#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define MAXIN 300000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
#define Fail puts("-1 -1")
typedef long long LL;
const int N=207;

int A[N][N];
bool ok[N][N],vis[N][N];
char IN[MAXIN],*SS=IN,*TT=IN;

inline int read()
{
	int now=0,f=1;register char c=gc();
	for(;!isdigit(c);c=='-'&&(f=-1),c=gc());
	for(;isdigit(c);now=now*10+c-'0',c=gc());
	return now*f;
}
inline void Expand(int x,int y)
{
	ok[x-1][y-1]=ok[x-1][y]=ok[x-1][y+1]=1, ok[x][y-1]=ok[x][y+1]=1, ok[x+1][y-1]=ok[x+1][y]=ok[x+1][y+1]=1;
}

int main()
{
	int n=read(),m=read(),K=read();
	for(int i=1; i<=n; ++i)
		for(int j=1; j<=m; ++j) A[i][j]=read();
	for(int i=1; i<=n; ++i)
		for(int j=1; j<=m; ++j) ok[i][j]=read();
	vis[0][0]=vis[n+1][m+1]=1;
	for(int i=1; i<=n; ++i) vis[i][0]=vis[i][m+1]=1;
	for(int i=1; i<=m; ++i) vis[0][i]=vis[n+1][i]=1;

	int T=read(),now=K,get=0;
	for(int x,y; T--; )
	{
		x=read(),y=read();
		if(!ok[x][y]||vis[x][y]) {Fail; return 0;}
		if(A[x][y]<=0&&now<10) {Fail; return 0;}
		if(A[x][y]>0) now+=A[x][y], now>K&&(now=K);
		else now-=10, get+=10;
		vis[x][y]=1, Expand(x,y);
	}
	printf("%d %d\n",now,get);

	return 0;
}

B 随机生成树(贪心)

题目链接

//不用建树的。。确定fa的时候判下颜色就好了。
#include <cstdio>
#include <cctype>
#include <algorithm>
#define gc() getchar()
#define MAXIN 300000
//#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++)
typedef long long LL;
const int N=5e5+5;

int Enum,H[N],nxt[N<<1],to[N<<1],col[N],fa[N],Ans;
char IN[MAXIN],*SS=IN,*TT=IN;

inline int read()
{
	int now=0;register char c=gc();
	for(;!isdigit(c);c=gc());
	for(;isdigit(c);now=now*10+c-'0',c=gc());
	return now;
}
#define AE(u,v) to[++Enum]=v,nxt[Enum]=H[u],H[u]=Enum
void Init(int n)
{
	for(int i=1; i<=n; ++i)
		for(int j=i+i,ci=col[i]; j<=n; j+=i)
			if(ci!=col[j]&&!fa[j]) fa[j]=i;
	for(int i=n; i; --i)
		for(int j=i+i; j<=n; j+=i)
			if(!fa[j]) fa[j]=i;
	for(int i=2; i<=n; ++i) AE(fa[i],i);
}
void DFS(int x,int c)
{
	if(c!=col[x]) c=col[x], ++Ans;
	for(int i=H[x]; i; i=nxt[i]) DFS(to[i],c);
}

int main()
{
//	freopen("B.in","r",stdin);
//	freopen(".out","w",stdout);

	int n=read();
	for(int i=1; i<=n; ++i) col[i]=read();
	Init(n);
	Ans=1, DFS(1,col[1]), printf("%d\n",Ans);

	return 0;
}

C 洞穴(倍增Floyd/bitset)

题目链接

倍增Floyd:

//147ms	620KB
//可以Floyd+倍增。然后就做完了。预处理是2的幂啊!
#include <cstdio>
#include <cctype>
#include <bitset>
#include <algorithm>
#define gc() getchar()
typedef long long LL;
const int N=101,M=1e4+5;

int n;
struct Matrix
{
	std::bitset<N> A[N];
	inline void Init(int n)
	{
		for(int i=0; i<n; ++i) A[i].set(i);
	}
}S,pw[31];

inline int read()
{
	int now=0;register char c=gc();
	for(;!isdigit(c);c=gc());
	for(;isdigit(c);now=now*10+c-'0',c=gc());
	return now;
}
inline Matrix Mul(const Matrix &x,const Matrix &y)
{
	Matrix ans;
	for(int k=0; k<n; ++k)
		for(int i=0; i<n; ++i)
			if(x.A[i][k]) ans.A[i]|=y.A[k];
	return ans;
}
void Solve()
{
	int k=read(),u=read()-1,v=read()-1;
	Matrix t; t.Init(n);//每个点自身可达。赋值一个t=S竟然很慢。。
	for(int i=29; ~i; --i)
		if(k>>i&1) t=Mul(t,pw[i]);
	puts(t.A[u][v]?"YES":"NO");
}

int main()
{
//	freopen("C.in","r",stdin);
//	freopen("my.out","w",stdout);

	n=read();
	for(int m=read(); m--; S.A[read()-1].set(read()-1));
	pw[0]=S;
	for(int i=1; i<=29; ++i) pw[i]=Mul(pw[i-1],pw[i-1]);//not pw[i-1]*S...
	for(int Q=read(); Q--; Solve());

	return 0;
}

优化:

//8ms	492KB
//因为不需要关心任意两点的可达状态,只关心从u出发多少步能到哪些点。令f[i][j][k]表示走2^i步时j是否可以到k,就可以省去Floyd了。。
#include <cstdio>
#include <cctype>
#include <bitset>
#include <algorithm>
#define gc() getchar()
#define BIT 29
const int N=101;

std::bitset<N> f[30][N];

inline int read()
{
	int now=0;register char c=gc();
	for(;!isdigit(c);c=gc());
	for(;isdigit(c);now=now*10+c-'0',c=gc());
	return now;
}

int main()
{
	int n=read();
	for(int m=read(),u; m--; u=read()-1,f[0][u].set(read()-1));

	for(int i=1; i<=BIT; ++i)
		for(int j=0; j<n; ++j)
			for(int k=0; k<n; ++k)
				if(f[i-1][j][k]) f[i][j]|=f[i-1][k];

	for(int Q=read(),u,v,k; Q--; )
	{
		k=read(),u=read()-1,v=read()-1;
		std::bitset<N> ans,tmp;
		ans.set(u);
		for(int i=BIT; ~i; --i)
			if(k>>i&1)
			{
				tmp=ans, ans.reset();
				for(int j=0; j<n; ++j)
					if(tmp[j]) ans|=f[i][j];
			}
		puts(ans[v]?"YES":"NO");
	}

	return 0;
}
posted @ 2018-10-29 07:54  SovietPower  阅读(178)  评论(0编辑  收藏  举报