目录
-
2018.10.28 牛客提高集训营7 - A 中国式家长2(模拟)
- B 随机生成树(贪心)
- C 洞穴(倍增Floyd/bitset)
期望得分:100+100+100
实际得分:100+100+100(0)
好不容易良心场,但是。。。
跑得快了,但是分没了。
预处理写错了,为什么上面两个还能过对拍啊==
比赛链接
A 中国式家长2(模拟)
题目链接
#include
#include
#include
#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
#include
#include
#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
#include
#include
#include
#define gc() getchar()
typedef long long LL;
const int N=101,M=1e4+5;
int n;
struct Matrix
{
std::bitset A[N];
inline void Init(int n)
{
for(int i=0; i>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
#include
#include
#include
#define gc() getchar()
#define BIT 29
const int N=101;
std::bitset 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 ans,tmp;
ans.set(u);
for(int i=BIT; ~i; --i)
if(k>>i&1)
{
tmp=ans, ans.reset();
for(int j=0; j