T1 暴雨

解题思路

\(f_{i,j,k,0/1}\) 表示前 i 个铲平 j 个当前最高的是 k 并且当前是 奇数/偶数 的方案数。

由于只可以铲平 k 块,因此对于同一种 \(i,j\) 而言高度只可能有 k+1 种,这些我们可以用 set 预处理出来。。

然后前后都做一遍 DP 在合并的时候枚举最高高度,同时枚举左右的最大值取值计入答案就好了。

code

#include <bits/stdc++.h>
#define ull unsigned long long
#define f() cout<<"Failed"<<endl
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=25e3+10,mod=1e9+7;
int n,m,num[N];long long ans;
struct Node
{
int s[N],f[N][26][30][2],rec[N][30],all[N];
unordered_map<int,int> mp[N];
set<int> se;
void solve()
{
for(int i=0;i<=n;i++)
{
for(auto it=se.begin();it!=se.end();it++)
mp[i].insert(make_pair((*it),++all[i])),rec[i][all[i]]=(*it);
if(mp[i].find(s[i])==mp[i].end()) mp[i].insert(make_pair(s[i],++all[i])),rec[i][all[i]]=s[i];
se.insert(s[i]); if(se.size()>m+1) se.erase(se.begin());
}
f[0][0][1][0]=1;
for(int i=0;i<n;i++)
for(int j=0;j<=m;j++)
for(int k=1;k<=all[i];k++)
for(int pos=0;pos<=1;pos++)
if(f[i][j][k][pos])
{
int val=max(s[i+1],rec[i][k]),p=pos^(val-s[i+1])&1;
int id=mp[i+1].find(val)->second;
f[i+1][j][id][p]=(f[i+1][j][id][p]+f[i][j][k][pos])%mod;
if(j>=m) continue;
val=rec[i][k]; id=mp[i+1].find(val)->second; p=pos^(val&1);
f[i+1][j+1][id][p]=1ll*(1ll*f[i+1][j+1][id][p]+1ll*f[i][j][k][pos])%mod;
}
}
}pre,suf;
signed main()
{
freopen("rain.in","r",stdin); freopen("rain.out","w",stdout);
n=read(); m=read();
for(int i=1;i<=n;i++) pre.s[i]=num[i]=read(),suf.s[n-i+1]=num[i];
pre.solve(); suf.solve();
for(int i=1;i<=n;i++)
for(int j=0;j<=m;j++)
for(int k=1;k<=pre.all[i];k++)
if(pre.rec[i-1][k]<num[i])
for(int pos=0;pos<=1;pos++)
if(pre.f[i-1][j][k][pos])
for(int q=1;q<=suf.all[n-i];q++)
if(suf.rec[n-i][q]<=num[i])
ans=(ans+1ll*pre.f[i-1][j][k][pos]*suf.f[n-i][m-j][q][pos])%mod;
printf("%lld",ans);
return 0;
}

T2 AVL 树

解题思路

首先对于整棵树我们可以初始化出来对于不同深度的树至少有多少节点。

然后对于子树进行搜索优先搜左子树,每次跳父亲看是否可以加入,由于这是一颗 AVL 树,因此树高接近 \(log\) 。

于是我们就可以对于父亲节点来更新自己的限制,并且根据左子树来更新右子树的限制。

code

#include <bits/stdc++.h>
#define int long long
#define ull unsigned long long
#define f() cout<<"Failed"<<endl
#define ls son[x][0]
#define rs son[x][1]
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=5e5+10;
int n,m,root,mxdep[N],dep[N],use[N],lim[N],g[50],fa[N],son[N][2];
bool vis[N];
void dfs(int x)
{
dep[x]=dep[fa[x]]+1; mxdep[x]=dep[x];
if(ls) dfs(ls),mxdep[x]=max(mxdep[x],mxdep[ls]);
if(rs) dfs(rs),mxdep[x]=max(mxdep[x],mxdep[rs]);
}
bool judge(int x)
{
int temp=max(dep[x],use[x]),cnt=0;
while(x)
{
cnt+=vis[x]^1; temp=max(temp,use[x]);
if(x==son[fa[x]][0]&&son[fa[x]][1])
cnt+=g[max(temp-1,lim[son[fa[x]][1]])-dep[fa[x]]];
x=fa[x];
}
return cnt<=m;
}
void insert(int x)
{
int temp=use[x]=max(use[x],dep[x]);
while(x)
{
m-=vis[x]^1; vis[x]=true; use[x]=max(use[x],temp);
if(x==son[fa[x]][0]&&son[fa[x]][1]&&!vis[son[fa[x]][1]])
lim[son[fa[x]][1]]=max(lim[son[fa[x]][1]],use[x]-1);
x=fa[x];
}
}
void work(int x)
{
int tmp1=ls,tmp2=rs; if(mxdep[ls]>=lim[x]) swap(tmp1,tmp2);
lim[tmp1]=max(lim[tmp1],lim[x]-1); lim[tmp2]=max(lim[tmp2],lim[x]);
}
void solve(int x)
{
if(judge(x)) insert(x);
if(ls&&rs) work(x);
else if(ls) lim[ls]=max(lim[ls],lim[x]);
else if(rs) lim[rs]=max(lim[rs],lim[x]);
if(ls) solve(ls); if(rs) solve(rs);
}
signed main()
{
freopen("avl.in","r",stdin); freopen("avl.out","w",stdout);
n=read(); m=read();
g[1]=1; for(int i=2;i<=40;i++) g[i]=g[i-1]+g[i-2]+1;
for(int i=1;i<=n;i++)
{
fa[i]=read();
if(~fa[i]&&fa[i]<i) son[fa[i]][1]=i;
else if(~fa[i]&&fa[i]>i) son[fa[i]][0]=i;
else root=i;
}
fa[root]=0; dfs(root); solve(root);
for(int i=1;i<=n;i++) printf("%lld",(int)vis[i]);
return 0;
}

T3 挖掘机

解题思路

比较暴力的一个思路就是对于每一个点求出它只操作一次可以到达的最远位置,然后依次跳链表。

这个东西是可以倍增优化的,每次跳 \(2^i\) 步,代码实现也不太难。。

只可惜我一直以为是线段树维护。。

code

#include <bits/stdc++.h>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
return x*f;
}
const int N=1e5+10;
int n,m,q,len,nxt[13][N],f[13][N][18];
char s[13][N];
void solve()
{
int dep,l,r,ans=0; dep=read(); l=read(); r=read();
for(int i=1;i<=dep;i++)
{
int pos=l;
if(s[i][pos]=='.') pos=nxt[i][pos]+1;
for(int j=17;j>=0&&pos<=r;j--)
if(f[i][pos][j]&&f[i][pos][j]<=r)
ans+=1ll<<j,pos=f[i][pos][j];
if(s[i][pos]=='.') pos=nxt[i][pos]+1;
if(pos<=r) ans++;
}
printf("%d\n",ans);
}
void Init_Work(int pos)
{
for(int i=m;i>=1;i--)
{
if(s[pos][i]=='X') f[pos][i][0]=i+len;
else f[pos][i][0]=nxt[pos][i]+len+1;
for(int j=0;f[pos][i][j];j++)
f[pos][i][j+1]=f[pos][f[pos][i][j]][j];
}
}
signed main()
{
freopen("blueshit.in","r",stdin); freopen("blueshit.out","w",stdout);
n=read(); m=read(); len=read(); q=read();
for(int i=1;i<=n;i++) scanf("%s",s[i]+1);
for(int i=1;i<=n;i++)
for(int j=m,las;j>=1;j--)
{
if(s[i][j]!=s[i][j+1]) las=j;
nxt[i][j]=las;
}
for(int i=1;i<=n;i++) Init_Work(i);
while(q--) solve();
return 0;
}

T4 游戏

大坑未补

NOIP模拟70的更多相关文章

  1. Noip模拟70 2021.10.6

    T1 暴雨 放在第一道的神仙题,不同的做法,吊人有的都在用线段树维护$set$预处理 我是直接$dp$的,可能代码的复杂度比那种的稍微小一点 设$f[i][j][p][0/1]$表示考虑了前$i$列, ...

  2. CH Round #58 - OrzCC杯noip模拟赛day2

    A:颜色问题 题目:http://ch.ezoj.tk/contest/CH%20Round%20%2358%20-%20OrzCC杯noip模拟赛day2/颜色问题 题解:算一下每个仆人到它的目的地 ...

  3. 10.17 NOIP模拟赛

    目录 2018.10.17 NOIP模拟赛 A 咒语curse B 神光light(二分 DP) C 迷宫maze(次短路) 考试代码 B 2018.10.17 NOIP模拟赛 时间:1h15min( ...

  4. NOIP模拟赛-2018.11.5

    NOIP模拟赛 好像最近每天都会有模拟赛了.今天从高二逃考试跑到高一机房,然而高一也要考试,这回好像没有拒绝的理由了. 今天的模拟赛好像很有技术含量的感觉. T1:xgy断句. 好诡异的题目,首先给出 ...

  5. 【HHHOJ】NOIP模拟赛 捌 解题报告

    点此进入比赛 得分: \(30+30+70=130\)(弱爆了) 排名: \(Rank\ 22\) \(Rating\):\(-31\) \(T1\):[HHHOJ260]「NOIP模拟赛 捌」Dig ...

  6. NOIP模拟题17.9.26

    B 君的任务(task)[题目描述]与君初相识,犹如故人归.B 君看到了Z 君的第一题,觉得很难.于是自己出了一个简单题.你需要完成n 个任务,第i 任务有2 个属性ai; bi.其中ai 是完成这个 ...

  7. NOIP模拟17.9.22

    NOIP模拟17.9.22 前进![问题描述]数轴的原点上有一只青蛙.青蛙要跳到数轴上≥

  8. NOIP模拟 17.8.17

    NOIP模拟17.8.17 A 小 G 的字符串文件名 输入文件 输出文件 时间限制 空间限制str.pas/c/cpp str.in str.out 1s 128MB[题目描述]有一天,小 L 给小 ...

  9. NOIP模拟 17.8.16

    NOIP模拟17.8.16 A 债务文件名 输入文件 输出文件 时间限制 空间限制debt.pas/c/cpp debt.in debt.out 1s 128MB[题目描述]小 G 有一群好朋友,他们 ...

  10. NOIP模拟 17.8.14

    NOIP模拟17.8.14 (天宇哥哥考察细心程度的题) [样例解释]如果删去第一个 1:在[3,1,2]中有 3 个不同的数如果删去 3:在[1,1,2]中有 2 个不同的数如果删去第二个 1:在[ ...

随机推荐

  1. Mac 修改版本号

    修改版本号 在安装某些软件(XCode)的过程中, 系统会提示版本低,需要升级到高版本, 而很多人不想升级而需要安装这些软件, 此时只需将版本号修改成软件安装要求的版本号就可以了. 由于SystemV ...

  2. c# ManualResetEventSlim

    前言 后续会把异步编程的ManualResetEventSlim 深入写完,先简单介绍一下吧. ManualResetEventSlim 有set 方法和 reset .wait.dispose方法. ...

  3. 重新整理数据结构与算法(c#)—— 算法套路二分法[二十四]

    前言 前面写过二分法使用的是递归手法,然后该节才有不递归的方式执行. 二分法的时间复杂度为log(2)n.空间复杂度为:1. 正文 代码: static void Main(string[] args ...

  4. 【Nano Framework ESP32篇】WS2812 彩色灯带实验

    地球人皆知,许多物联网教程作者的心中都深爱着一灯大师,所以第一个例程总喜欢点灯,高级一点的会来个"一闪一闪亮晶晶".老周今天要扯的也是和灯有关的,但不单纯地点个灯,那样实在不好玩, ...

  5. 07cj031,07CJ03-1图集免费下载

    简介 07CJ03-1轻钢龙骨石膏板隔墙.吊顶图集是中国建筑标准设计研究院组织编写的一部针对轻钢龙骨.石膏板材料用于非承重隔墙.室内吊顶装修的装修.建造参考资料,为用户提供专业的建造参考 下载 有需要 ...

  6. 剑指offer53(Java)-在排序数组中查找数字(简单)

    题目: 统计一个数字在排序数组中出现的次数. 示例 1: 输入: nums = [5,7,7,8,8,10], target = 8输出: 2示例 2: 输入: nums = [5,7,7,8,8,1 ...

  7. 力扣596(MySQL)-超过5名学生的课(简单)

    题目: 表: Courses 编写一个SQL查询来报告 至少有5个学生 的所有班级. 以 任意顺序 返回结果表. 查询结果格式如下所示 示例1:  解题思路: 使用group by按 班级 进行分组后 ...

  8. CF1832B Maximum Sum 题解

    [题目描述] 给定一个长度为 \(n\) 的数列,其中每个元素互不相同,进行 \(k\) 次操作,每次可以选择删除序列中最小的两个数或最大的一个数.求操作后剩余数的和的最大值. [思路] 我们构造一组 ...

  9. Duang,您的钉钉应用已上线!云开发5分钟快速打造钉钉会议室预定系统

    简介: 5分钟可以干什么?喝一杯咖啡,回一封邮件,还是开发上线一个钉钉应用.云开发平台联合钉钉开发平台推出0门槛打造你的第一个钉钉应用的活动,完成相应任务后,即可领取精美奖品.春暖花开,领个背包去踏春 ...

  10. 双引擎驱动Quick BI十亿数据0.3秒分析,首屏展示时间缩短30%

    ​简介:在规划中,Quick BI制定了产品竞争力建设的三大方向,包括Quick(快)能力.移动端能力和集成能力.针对其中的产品"报表查看打开慢""报表开发数据同步慢&q ...