加载中…

返回上一页

CSP-S模拟6

下发文件和题解

A. 玩水(512MB 1000ms)

能走出分离路径,那么一定是斜线. 不难发现,只有这三种情况能够符合:

  1. 同行右侧第一个位置(下图黄线所标)

 

 

  1. 同列下侧第一个位置

 

(同理我就不画了)

 

  1. 第二条斜线至少在第一条斜线的右一下一

 

因此模拟这三种情况即可. (查找时由于需要查询左上方是否已有斜线,在赛时害怕 T 用的二维 bit,其实也可以暴力查找或者用布尔数组标记)

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define rll rg ll
#define maxn 1001
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
static inline ll read()
{
	rll f=0,x=0;rg char ch=getchar();
	while(ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar();
	return f?-x:x;
}
static inline void write(rll x)
{
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);putchar(x%10|'0');
}

template<typename t,size_t sz>
class bit
{
#define lowbit(x) (x&-x)
private:
	t c[sz];
public:
	inline void clear() { memset(c,0,sizeof(c)); }
	inline void update(rll x,rll n,rll v) { for(rll i=x;i<=n;i+=lowbit(i)) c[i]+=v; }
	inline ll query(rll x) { rll ans=0; for(rll i=x;i;i-=lowbit(i)) ans+=c[i]; return ans; }
};

ll T,n,m;
bool ans;
char mp[maxn][maxn];
bit<ll,maxn> t[maxn];
static inline ll query(rll x,rll y) { rll ans=0;for(rll i=x;i;i-=lowbit(i)) ans+=t[i].query(y);return ans; }
static inline void upd(rll x,rll y,rll v) { for(rll i=x;i<=n;i+=lowbit(i)) t[i].update(y,m,v); }
int main()
{
	T=read();
	while(T--)
	{
		ans=0;n=read();m=read();for(rll i=1;i<=n;i++) t[i].clear();
		for(rll i=1;i<=n;i++) scanf("%s",mp[i]+1);
		for(rll i=1;i<n;i++)
		{
			for(rll j=2;j<=m;j++)
				if(mp[i][j]==mp[i+1][j-1])
				{
					if(i-1&&query(i-1,j-1)) { ans=1; break; }
					if(((i!=n-1)&&mp[i+1][j]==mp[i+2][j-1])||((j!=m)&&mp[i][j+1]==mp[i+1][j])) { ans=1; break; }
					upd(i,j,1);
				}
			if(ans) break;
		}
		write(ans);putn;
	}
	return 0;
}

B. AVL 树(256MB 1000ms)

暂略.

参考:[1] [2]

点击查看代码
#include<bits/stdc++.h>
#define ll long long
#define rg register
#define rll rg ll
#define maxn 500001
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
static inline ll read()
{
	rll f=0,x=0;rg char ch=getchar();
	while(ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar();
	return f?-x:x;
}
static inline void write(rll x)
{
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);putchar(x%10|'0');
}
ll n,lg,k,rt;
ll dp[maxn],fa[maxn],d[maxn];
ll mxd[maxn],h[maxn],rmnd[maxn];
bool ans[maxn];
vector<ll> g[maxn];
static inline void dfs(rll x,rll fa)
{
	mxd[x]=d[x]=d[fa]+1;
	if(g[x][0]) dfs(g[x][0],x),mxd[x]=max(mxd[x],mxd[g[x][0]]);
	if(g[x][1]) dfs(g[x][1],x),mxd[x]=max(mxd[x],mxd[g[x][1]]);
}
static inline void dfs1(rll x)
{
	rll x1=x,y=d[x],tot=0;
	while(x1)
	{
		if(!ans[x1]) tot++;y=max(y,h[x1]);
		if(x1<fa[x1]&&(!ans[g[fa[x1]][1]])) tot+=dp[max(y-1,rmnd[g[fa[x1]][1]])-d[fa[x1]]];
		x1=fa[x1];
	}
	if(tot<=k)
	{
		x1=x;y=h[x]=max(h[x],d[x]);
		while(x1)
		{
			if(!ans[x1]) ans[x1]=1,k--;
			h[x1]=max(h[x1],y);
			if(x1<fa[x1]&&g[fa[x1]][1]&&(!ans[g[fa[x1]][1]])) rmnd[g[fa[x1]][1]]=max(rmnd[g[fa[x1]][1]],h[x1]-1);
			x1=fa[x1];
		}
	}
	if(g[x][0]&&g[x][1])
	{
		if(mxd[g[x][0]]<rmnd[x]) rmnd[g[x][0]]=max(rmnd[g[x][0]],rmnd[x]-1),rmnd[g[x][1]]=max(rmnd[g[x][1]],rmnd[x]);
		else rmnd[g[x][0]]=max(rmnd[g[x][0]],rmnd[x]),rmnd[g[x][1]]=max(rmnd[g[x][1]],rmnd[x]-1);
		dfs1(g[x][0]);dfs1(g[x][1]);return;
	}
	if(g[x][0])
		rmnd[g[x][0]]=max(rmnd[g[x][0]],rmnd[x]),dfs1(g[x][0]);
	if(g[x][1])
		rmnd[g[x][1]]=max(rmnd[g[x][1]],rmnd[x]),dfs1(g[x][1]);
}
int main()
{
	n=read();k=read();lg=50;
	dp[1]=1;dp[2]=2;for(rll i=3;i<=lg;i++) dp[i]=dp[i-1]+dp[i-2]+1;
	for(rll i=1;i<=n;i++) g[i]={0,0};
	for(rll i=1,p;i<=n;i++)
	{
		p=read();
		if(p^-1) fa[i]=p,g[p][(bool)(p<i)]=i;else rt=i;
	}
	dfs(rt,0);dfs1(rt);for(rll i=1;i<=n;i++) write(ans[i]);
	return 0;
}

C. 暴雨(512MB 1200ms)

一道明显的 dp.

dp[i][j][p][0/1] 表示已经 dp 到第 i 列,其中土块高度最大值为 j 且后面要存在高度至少为 j 的土块,在前 i 列一共挖掉了 p列泥土. 0/1 表示当前积水的体积是奇数还是偶数.

很明显,1≤hi≤109,第二维数组是开不下的. 考虑一下转移的实质,发现只有那最高的 25 列对答案才是有贡献的. 因此离散化记录一下最高的那 25 个的编号即可.

转移之前记录一下几个值:

hi[i][j]:前 i 列第 j 大的土块高度;
cnt[i]:前 i 列有多少个可进行转移的状态.

那么有以下转移:

A.hi[i][j] > a[i+1]

dp[i+1][newj][p][0/1] += dp[i][j][p][0/1]

dp[i+1][newj][p+1][0/1] += dp[i][j][p][0/1]

A.hi[i][j] ≤ a[i+1]

dp[i+1][ai+1][p][0/1] += dp[i][j][p][0/1]

dp[i+1][newj][p+1][0/1] += dp[i][j][p][0/1].

由于 dp 的时候后面的土块高度对前面的土块高度有影响,所以我们分别正着走一遍、倒着走一遍 dp 即可.

点击查看代码
#include<bits/extc++.h>
#define ll int
#define rg register
#define rll rg ll
#define maxn 25001
#define maxm 26
#define mod 1000000007
#define put_ putchar(' ')
#define putn putchar('\n')
using namespace std;
static inline ll read()
{
	rll f=0,x=0;rg char ch=getchar();
	while(ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
	while(ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+(ch^'0'),ch=getchar();
	return f?-x:x;
}
static inline void write(rll x)
{
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);putchar(x%10|'0');
}
ll n,k;
ll ans;
ll h[maxn],id[maxn];
class dp
{
public:
	ll h[maxn];
	ll dp[maxn][maxm][maxm][2];
	ll hi[maxn][maxm]/*前i列第几大的高度*/,cnt[maxn];
	multiset<ll> s;
	__gnu_pbds::cc_hash_table<ll,ll> mp[maxn];// map
	inline void DP()
	{
		s.insert(0);cnt[0]=1;dp[0][1][0][0]=1;
		for(rll i=1,j;i<=n;i++)
		{
			s.insert(h[i]);j=1;
			for(rg set<ll>::iterator it=--s.end();j<=k+1;it--,j++)
			{
				mp[i][*it]=++cnt[i],hi[i][mp[i][*it]]=*it;
				if(it==s.begin()) break;
			}
		}
		// for(auto x:s) write(x),putchar(' ');
		for(rll i=0;i<n;i++)
			for(rll j=1;j<=cnt[i];j++)
				for(rll p=0;p<=k;p++)
					for(rll s=0;s<=1;s++)
						if(dp[i][j][p][s])
						{
							if(hi[i][j]>h[i+1])
							{
								dp[i+1][mp[i+1][hi[i][j]]][p][hi[i][j]-h[i+1]&1^s]=((long long)dp[i+1][mp[i+1][hi[i][j]]][p][hi[i][j]-h[i+1]&1^s]+dp[i][j][p][s])%mod;// ,write(dp[i+1][mp[i+1][hi[i][j]]][p][hi[i][j]-h[i+1]&1^s]),put_;
								if(p+1<=k) dp[i+1][mp[i+1][hi[i][j]]][p+1][hi[i][j]&1^s]=((long long)dp[i+1][mp[i+1][hi[i][j]]][p+1][hi[i][j]&1^s]+dp[i][j][p][s])%mod;// ,write(dp[i+1][mp[i+1][hi[i][j]]][p+1][hi[i][j]&1^s]),put_;
							}
							else
							{
								dp[i+1][mp[i+1][h[i+1]]][p][s]=((long long)dp[i+1][mp[i+1][h[i+1]]][p][s]+dp[i][j][p][s])%mod;// ,write(dp[i+1][mp[i+1][h[i+1]]][p][s]),put_;
								if(p+1<=k) dp[i+1][mp[i+1][hi[i][j]]][p+1][hi[i][j]&1^s]=((long long)dp[i+1][mp[i+1][hi[i][j]]][p+1][hi[i][j]&1^s]+dp[i][j][p][s])%mod;// ,write(dp[i+1][mp[i+1][hi[i][j]]][p+1][hi[i][j]&1^s]),put_;
							}
						}
	}
}a,b;
static inline bool cmp(rll x,rll y) { return h[x]>h[y]; }
int main()
{
	// s.insert(1);s.insert(2);write(*s.begin());
	n=read();k=read();
	if(n==1) { putchar('1'); return 0; }
	for(rll i=1;i<=n;i++) a.h[i]=b.h[n-i+1]=h[i]=read(),id[i]=i;
	sort(id+1,id+n+1,cmp);a.DP();b.DP();
	for(rll i=1;i<=n;i++)
	{
		if(h[id[i]]<h[id[k+1]]) break;
		for(rll j=a.cnt[id[i]-1];j;j--)
		{
			if(a.hi[id[i]-1][j]>h[id[i]]) break;
			for(rll l=b.cnt[n-id[i]];l;l--)
			{
				if(b.hi[n-id[i]][l]>=h[id[i]]) break;
				for(rll p=0;p<=k;p++)
					ans=(((long long)ans+(long long)a.dp[id[i]-1][j][p][0]*b.dp[n-id[i]][l][k-p][0]%mod)%mod+(long long)a.dp[id[i]-1][j][p][1]*b.dp[n-id[i]][l][k-p][1]%mod)%mod;
			}
		}
	}
	write(ans);
	return 0;
}

D. 置换(256MB 2000ms)

不会……

posted @ 2022-09-19 21:37  1Liu  阅读(30)  评论(0)    收藏  举报