CSP-S模拟6
下发文件和题解
A. 玩水(512MB 1000ms)
能走出分离路径,那么一定是斜线. 不难发现,只有这三种情况能够符合:
- 同行右侧第一个位置(下图黄线所标)
- 同列下侧第一个位置
(同理我就不画了)
- 第二条斜线至少在第一条斜线的右一下一
因此模拟这三种情况即可. (查找时由于需要查询左上方是否已有斜线,在赛时害怕 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)
暂略.
点击查看代码
#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)
不会……
--END--



浙公网安备 33010602011771号
我的博客: 𝟷𝙻𝚒𝚞
本文链接: https://www.cnblogs.com/1Liu/p/16709170.html
版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!