上午 NOIP 太憋屈了,我要切水恢复一下信心(

希望 cy 别看见

A - Daily Cookie

在题目限制中,已经确定 \(S\) 中 @ 字符的个数多于 \(D\)。所以我们直接数 . 的个数加上 \(D\) 就可以。

时间复杂度 \(O(n)\)。

点击查看代码
#include <iostream>
#include <cstdio>
using namespace std;
const int N=105;
char s[N];
int d,n,ans;
int main(){
scanf("%d %d",&n,&d);
scanf("%s",s+1);
for(int i=1;i<=n;i++)ans+=(s[i]=='.');
ans+=d;
printf("%d\n",ans);
return 0;
}

B - Daily Cookie 2

跟上面那题一样,这次我们直接维护一个指针从 \(n\) 扫到 \(1\),把最先遇到的前 \(D\) 个 @ 变为 .,最后输出即可。

时间复杂度 \(O(n)\)。

点击查看代码
#include <iostream>
#include <cstdio>
using namespace std;
const int N=105;
char s[N];
int d,n,ans;
int main(){
scanf("%d %d",&n,&d);
scanf("%s",s+1);
int it=n;
for(int i=1;i<=d;i++){
while(it&&s[it]!='@')it--;
s[it]='.';
}
for(int i=1;i<=n;i++){
printf("%c",s[i]);
}
return 0;
}

C - Kaiten Sushi

如果存在 \(i,j\),满足 \(i<j\) 且 \(A_i<A_j\),那么 \(j\) 是一定吃不到寿司的,因为 \(j\) 可以吃的寿司都会被 \(i\) 提前偷吃。

所以我们去除所有的 \(j\),则剩下的 \(i\) 一定满足 \(A_i\) 单调递减,直接二分查找第一个人即可。

时间复杂度 \(O(n\log n)\)。

点击查看代码
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int N=2e5+10;
int n,m,t;
int a[N],b[N];
int lower(int x){
int l=1,r=t;
while(l<r){
int mid=(l+r)>>1;
if(a[mid]<=x)r=mid;
else l=mid+1;
}
return l;
}
int main(){
scanf("%d %d",&n,&m);
for(int i=1,x;i<=n;i++){
scanf("%d",&x);
if(!t||a[t]>x)a[++t]=x,b[t]=i;
}
for(int i=1,x;i<=m;i++){
scanf("%d",&x);
if(x<a[t])printf("-1\n");
else printf("%d\n",b[lower(x)]);
}
return 0;
}

因为偷懒想用 lower_bound 花费了不少时间。

D - Keep Distance

入机搜索题。

枚举 \(A_1\) 的取值,然后搜索剩下的数。

纯爆搜会超时,我们只需加上一个小优化,假设当前要填第 \(A_i\) 位,因为接下来 \(i\) 每增加 \(1\),\(A_i\) 就会增加 \(10\),所以此时的 \(A_i\) 必须满足 \(A_{i-1}+(n-i+1)\times 10\le M\),否则就没有搜索的必要了。

可以搜两次,第一次统计方案数,第二次输出方案。

点击查看代码
#include <iostream>
#include <cstdio>
using namespace std;
int n,m,a[13],ans;
inline void print(){
for(int i=1;i<=n;i++)printf("%d ",a[i]);
printf("\n");
}
inline void dfs(int x){
if(x>n)print();
else{
for(int i=10;a[x-1]+i<=m;i++){
if((n-x+1)*10+a[x-1]>m)return;
a[x]=a[x-1]+i;
dfs(x+1);
a[x]=0;
}
}
return;
}
inline void DFS(int x){
if(x>n){
ans++;
}else{
for(int i=10;a[x-1]+i<=m;i++){
if((n-x+1)*10+a[x-1]>m)return;
a[x]=a[x-1]+i;
DFS(x+1);
a[x]=0;
}
}
return;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
a[1]=i;
DFS(2);
}
printf("%d\n",ans);
for(int i=1;i<=m;i++){
a[1]=i;
dfs(2);
}
return 0;
}

这道题最开始写时数组开小,后面调好后提交没有发现 TLE,比赛还有 \(10\min\) 的是否发现没过,差点忘了。

E - Expansion Packs

期望题,不会。

F - Falling Bars

读题读了好长时间。。。话说为什么我的 Atcoder Better 不能用了?

首先没一个条都可以表示成一条纵坐标为 \(x_i\),两个端点横坐标分别是 \([l_i,r_i]\) 的线段。

我们考虑按照初始时的纵坐标从大到小的顺序考虑它最后会移到第几排。

假设现在枚举到了第 \(i\) 条线段,我们枚举它下面的线段 \(j\),用 \(\min\{R_j\}-1\to R_i\)。

这样就得到了 \(O(n^2)\) 的算法。

事实上,可以直接用线段树维护 \([1,w]\) 上的区域,每计算出 \(R_i\),就用其更新 \([l_i,r_i]\) 上的区域,计算 \(R_i\) 时,就快速查询 \([l_i,r_i]\) 上的最小值。我的做法是区间取 \(\min\) 区间查 \(\min\) 线段树。但也有用区间赋值区间查 \(\min\) 的更为简单的做法(其实差不多)。

时间复杂度 \(O(n\log n)\)。

点击查看代码
#include <iostream>
#include <algorithm>
#include <cstdio>
#define ls (p<<1)
#define rs (p<<1|1)
using namespace std;
const int N=2e5+10,inf=1e9+10;
struct sgt{
int mn[N<<2],tag[N<<2];
bool used[N<<2];
void push_up(int p){
mn[p]=min(mn[ls],mn[rs]);
}
void push_down(int p){
if(!used[p])return;
mn[ls]=min(mn[ls],tag[p]);
mn[rs]=min(mn[rs],tag[p]);
tag[ls]=min(tag[ls],tag[p]);
tag[rs]=min(tag[rs],tag[p]);
used[ls]=used[rs]=1;
used[p]=0,tag[p]=inf;
}
void build(int p,int l,int r){
mn[p]=tag[p]=inf;used[p]=0;
if(l==r)return;
int mid=(l+r)>>1;
build(ls,l,mid),build(rs,mid+1,r);
return;
}
void change(int p,int l,int r,int L,int R,int v){
if(L<=l&&r<=R){
mn[p]=min(mn[p],v);
tag[p]=min(tag[p],v);
used[p]=1;
}else{
int mid=(l+r)>>1;
push_down(p);
if(L<=mid)change(ls,l,mid,L,R,v);
if(R>mid)change(rs,mid+1,r,L,R,v);
push_up(p);
}
return;
}
int ask(int p,int l,int r,int L,int R){
if(L<=l&&r<=R)return mn[p];
int mid=(l+r)>>1,cnt=inf;
push_down(p);
if(L<=mid)cnt=min(cnt,ask(ls,l,mid,L,R));
if(R>mid)cnt=min(cnt,ask(rs,mid+1,r,L,R));
push_up(p);return cnt;
}
}tr;
struct node{
int x,l,r,id;
}a[N];
bool cmp(node a,node b){
return a.x>b.x;
}
int h,w,n,ans[N];
int main(){
scanf("%d %d %d",&h,&w,&n);
for(int i=1,r,c,L;i<=n;i++){
scanf("%d %d %d",&r,&c,&L);
a[i]=node{r,c,c+L-1,i};
}
sort(a+1,a+1+n,cmp);
tr.build(1,1,w);
for(int i=1;i<=n;i++){
ans[a[i].id]=min(tr.ask(1,1,w,a[i].l,a[i].r)-1,h);
tr.change(1,1,w,a[i].l,a[i].r,ans[a[i].id]);
}
for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
return 0;
}

G - Tile Distance 3

翻译都没看完。

为啥我 Atcoder Better 突然没法用了啊!!!

随机推荐

  1. 什么是 Java 的 AOT(Ahead-Of-Time)?

    Java 的 AOT(Ahead-Of-Time) 1. 定义 AOT(Ahead-Of-Time)编译是与 JIT(Just-In-Time)相对的一种编译方式. 在 AOT 模式下,Java 字节 ...

  2. nodejs隐藏窗口启动redis服务,一个vbs文件即可

    网上也有很多类似的,但基本都是用nodejs调.vbs,然后间接调.bat,经过多番尝试发现其实合并为一个文件亦可 将如下内容保存为.vbs文件,如startRedis.vbs (在nw的根目录) s ...

  3. Missing Semester

    计算机教育中缺失的一课 The Missing Semester of Your CS Education 文档:https://missing-semester-cn.github.io/ 网课:h ...

  4. Python3_python2打包exe文件

    最近要把绿盟报告导出脚本打包成一个exe,原本是一个py2的文件Vulreport.py,我做了如下步骤. 1.py2topy3 Python3 2to3.py -w Vulreport.py 2.p ...

  5. mysql设置时区

    参考:https://blog.csdn.net/vkingnew/article/details/82149726 查看时区 show variables like '%time_zone%'; 设 ...

  6. java设置权限过滤器--防止用户未登录访问某些页面

    话不多说,上代码!!! package com.store.web.filter; import java.io.IOException; import javax.servlet.Filter; i ...

  7. SpringBoot整合Web层技术

    目录 1 SpringBoot整合Web层技术 1.1 SpringBoot整合Servlet 1.1.1 方式一 通过注解扫描完成Servlet组件的注册 1.1.1.1 创建Servlet 1.1 ...

  8. 理解 C# 中的各类指针

    目录 前言 对象引用(Object Reference) 指针(Pointer) 指针的声明和使用 指针可以指向的位置 可以声明指针的位置 指向值类型变量的指针 指向对象引用的指针 指向 GC Hea ...

  9. MCP SSE交互完整过程

    有关MCP的介绍文章很多,本文不细说,做一个时序图将完整过程说清楚.MCP协议主要通过两种技术实现:标准输入输出(stdio)和服务器发送事件(SSE),stdio(标准输入输出)是MCP协议在本地或 ...

  10. 基于StringUtils实现List和String字符串互转

    将以逗号分割的字符串转换成List类型: String ids= "1,2,32,59,96"; List<Long> idsList = Arrays.asList( ...