题解和总结——noip2019集训测试赛(一)贪吃蛇+字符串+都城
Problem A: 贪吃蛇
描述

Input

Output

Sample Input
【样例输入1】
4 5
##...
..1#@
432#.
...#.
【样例输出1】
4
【样例输入2】
4 4
#78#
.612
.543
..@.
【样例输出2】
6
【样例输入3】
3 2
3@
2#
1#
【样例输出3】
-1
这道题就是一个简单的广搜,储存蛇头位置,步数和蛇的身体的各个部分的位置。注意,要关照一下蛇不能越过自己的身体。
代码:
#include<bits/stdc++.h>
using namespace std;
struct zuobiao
{
int x,y;
}a[11];
struct data
{
int x,y,sum;
zuobiao number[10];
}b;
queue<data> q;
char ch;
int n,m,is[16][16],k,f[4][2]={{0,1},{1,0},{0,-1},{-1,0}};
bool vis[16][16],flag;
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
cin>>ch;
if(ch=='#')
{
is[i][j]=10;
}else{
if(ch=='@')
{
is[i][j]=11;
}else{
if(ch>='1'&&ch<='9')
{
k++;
b.number[ch-'0'].x=i;
b.number[ch-'0'].y=j;
if(ch=='1')
{
b.x=i;
b.y=j;
b.sum=0;
}
}
}
}
}
}
q.push(b);//放入队列
while(!q.empty())
{
data u=q.front();
data p=u;
q.pop();
for(int i=0;i<4;i++)
{
u=p;
int xx=u.number[1].x+f[i][0];
int yy=u.number[1].y+f[i][1];
int num=u.sum;
flag=0;
for(int i=1;i<k;i++)//可以咬尾巴,尾巴会走
{
if(xx==u.number[i].x&&yy==u.number[i].y)
{
flag=1;
break;
}
}
if(flag||is[xx][yy]==10||vis[xx][yy]||xx>n||xx<1||yy>m||yy<1)
{
continue;
}
if(is[xx][yy]==11)
{
printf("%d\n",num+1);
return 0;
}
for(int i=k;i>1;i--)//移动蛇身
{
u.number[i].x=u.number[i-1].x;
u.number[i].y=u.number[i-1].y;
}
u.sum++;
vis[u.number[1].x][u.number[1].y]=1;//更新
u.number[1].x=xx;
u.number[1].y=yy;
q.push(u);
}
}
puts("-1");//若无解
return 0;
}
Problem B: 字符串
UPD:本题字符集为全体小写字母
描述:

Input

Output

Sample Input
5
1 abc
3 abcabc
0 abc
3 aba
1 abababc
Sample Output
2
2
这一题题目描述明确地提示了一件事——本题是字符串题,虽然说了是强制在线,可能有点假,因为我们可以优化修改和查询的时间复杂度从而不理会强制在线带来的难题。
我们提前建好AC自动机的fail树记录好每个字符串的起始点,长度,并把它们合并到一起。 在fail树上的_a[s]_ 的值用线段树或者树状数组维护,dfs遍历打上时间戳。改修改的修改,该查询的查询,最后可以得出答案(某巨佬的想法)。
然后我说说个人有几个疑惑的点,为什么是这样做:
1.为什么可以用线段树或树状数组维护?

如图,点a的值加1,点b的值必定会加1。
2.这句话为什么?
add(dfn[num[i]]+size[num[i]],1);
很简单:

如果其中的4到6这个区间一起加了个1,在这个区间前和区间中的查找不会有什么影响,但区间后的一段就因为4到6加了个1,而被迫加了个1,所以我们在增加4到6区间时,也要相对应地在这个区间后减去1。
#include<bits/stdc++.h>
using namespace std;
int to[2000001],tot,nxt[2000001],head[2000001],len[2000001],cnt,num[2000001],dfn[2000001],indew,size[2000001],c[2000001],n,op[2000001],l,begi[2000001],mark;
char s[2000001],ch[2000001];
long long ans;
struct data
{
int b[26],fail;
}a[2000001];
void adde(int u,int v)
{
to[++tot]=v;
nxt[tot]=head[u];
head[u]=tot;
}
void build(char ch[],int id)
{
int root=0;
for(int i=0;i<len[id];i++)
{
int xx=ch[i]-'a';
if(!a[root].b[xx])
{
a[root].b[xx]=++cnt;
}
root=a[root].b[xx];
}
num[id]=root;
}
void fail()//建fail树
{
queue<int> q;
for(int i=0;i<26;i++)
{
if(a[0].b[i])
{
a[a[0].b[i]].fail=0;
q.push(a[0].b[i]);
}
}
while(!q.empty())
{
int u=q.front();
q.pop();
for(int i=0;i<26;i++)
{
if(a[u].b[i])
{
a[a[u].b[i]].fail=a[a[u].fail].b[i];
q.push(a[u].b[i]);
}else{
a[u].b[i]=a[a[u].fail].b[i];
}
}
}
for(int i=1;i<=cnt;i++)
{
adde(a[i].fail,i);
}
}
void dfs(int u)
{
dfn[u]=++indew;
size[u]=1;
for(int i=head[u];i;i=nxt[i])
{
int v=to[i];
dfs(v);
size[u]+=size[v];
}
}
int lowbit(int x)
{
return x&(-x);
}
void add(int x,int y)
{
for(;x<=indew;x+=lowbit(x))
{
c[x]+=y;
}
}
long long ask(int x)
{
int ans1=0;
for(;x;x-=lowbit(x))
{
ans1+=c[x];
}
return ans1;
}
void work(int l,int r)
{
long long root=0;
for(int i=l;i<=r;i++)
{
int xx=s[i]-'a';
root=a[root].b[xx];
ans+=ask(dfn[root]);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d%s",&op[i],ch);
len[i]=strlen(ch);
begi[i]=l+1;
build(ch,i);
for(int j=0;j<len[i];j++)
{
s[++l]=ch[j];
}
}
fail();//建fail树
dfs(0);
for(int i=1;i<=n;i++)
{
op[i]^=mark;
if(op[i]==1)//树状数组
{
add(dfn[num[i]],1);
add(dfn[num[i]]+size[num[i]],-1);
}else{
if(op[i]==2)
{
add(dfn[num[i]],-1);
add(dfn[num[i]]+size[num[i]],1);
}else{
ans=0;
work(begi[i],begi[i]+len[i]-1);
printf("%lld\n",ans);
mark^=abs(ans);
}
}
}
return 0;
}
Problem C: 都城
题目描述:

Input

Output

看题好像很玄乎地样子,但是我们画出图来发现——以一个点为都城所形成的树上相邻两点的计划更改数相差1且若a为b的father:ans[b]=ans[a]+1,反之则亦然。
那我们可以根据这一点想到了树形DP,两遍dfs,第一遍确定以一个点为都城的ans值,第二遍通过上边这个式子推出所有点的ans。
#include<bits/stdc++.h>
using namespace std;
struct data
{
int y,fa;//记录原计划是x通往y还是y通往x是高速公路
};
vector<data> a[100001];
int ans[100001],n,x,y;
void dfs(int u,int fa)
{
for(int i=0;i<a[u].size();i++)
{
data v=a[u][i];
if(v.y==fa)
{
continue;
}
if(!v.fa)//求ans[1]
{
ans[1]++;
}
dfs(v.y,u);
}
}
void dfs1(int u,int fa)
{
for(int i=0;i<a[u].size();i++)
{
data v=a[u][i];
if(v.y==fa)
{
continue;
}
if(!v.fa)//计算
{
ans[v.y]=ans[u]-1;
}else{
ans[v.y]=ans[u]+1;
}
dfs1(v.y,u);
}
}
int main()
{
scanf("%d",&n);
for(int i=1;i<n;i++)
{
scanf("%d%d",&x,&y);
a[x].push_back((data){
y,1
});
a[y].push_back((data){
x,0
});
}
dfs(1,-1);
dfs1(1,-1);
for(int i=1;i<=n;i++)
{
printf("%d\n",ans[i]);
}
return 0;
}
总结:
这次考的不太好,主要是第三题考场上没有注意到相邻两点的值相差1,只能打了一个暴搜。
题解和总结——noip2019集训测试赛(一)贪吃蛇+字符串+都城的更多相关文章
- noip2019集训测试赛(二十一)Problem B: 红蓝树
noip2019集训测试赛(二十一)Problem B: 红蓝树 Description 有一棵N个点,顶点标号为1到N的树.N−1条边中的第i条边连接顶点ai和bi.每条边在初始时被染成蓝色.高桥君 ...
- noip2019集训测试赛(二十一)Problem A: Colorful Balls
Problem A: Colorful Balls Description Snuke放了N个一排彩色的球.从左起第i个球的颜色是ci重量是wi她可以通过执行两种操作对这些球重新排序操作1:选择两个相 ...
- 【2016北京集训测试赛(十)】 Azelso (期望DP)
Time Limit: 1000 ms Memory Limit: 256 MB Description 题解 状态表示: 这题的状态表示有点难想...... 设$f_i$表示第$i$个事件经过之 ...
- 【2016北京集训测试赛(二)】 thr (树形DP)
Description 题解 (这可是一道很早就碰到的练习题然后我不会做不想做,没想到在Contest碰到欲哭无泪......) 题目大意是寻找三点对的个数,使得其中的三个点两两距离都为d. 问题在于 ...
- 【2016北京集训测试赛(八)】 crash的数列 (思考题)
Description 题解 题目说这是一个具有神奇特性的数列!这句话是非常有用的因为我们发现,如果套着这个数列的定义再从原数列引出一个新数列,它居然还是一样的...... 于是我们就想到了能不能用多 ...
- 【2016北京集训测试赛(十六)】 River (最大流)
Description Special Judge Hint 注意是全程不能经过两个相同的景点,并且一天的开始和结束不能用同样的交通方式. 题解 题目大意:给定两组点,每组有$n$个点,有若干条跨组 ...
- 【2016北京集训测试赛】river
HINT 注意是全程不能经过两个相同的景点,并且一天的开始和结束不能用同样的交通方式. [吐槽] 嗯..看到这题的想法的话..先想到了每个点的度为2,然后就有点不知所措了 隐隐约约想到了网络流,但并没 ...
- 【2016北京集训测试赛】azelso
[吐槽] 首先当然是要orzyww啦 以及orzyxq奇妙顺推很强qwq 嗯..怎么说呢虽然说之前零零散散做了一些概d的题目但是总感觉好像并没有弄得比较明白啊..(我的妈果然蒟蒻) 这题的话可以说是难 ...
- 2016北京集训测试赛(十七)Problem B: 银河战舰
Solution 好题, 又是长链剖分2333 考虑怎么统计答案, 我场上的思路是统计以一个点作为结尾的最长上升链, 但这显然是很难处理的. 正解的方法是统计以每个点作为折弯点的最长上升链. 具体的内 ...
随机推荐
- 夯实Java基础系列22:一文读懂Java序列化和反序列化
本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...
- MongoDB 学习笔记之 Aggregation Pipeline
Aggregation Pipeline: 常用操作符介绍: $project:包含.排除.重命名和显示字段 $match:查询,需要同find()一样的参数 $limit:限制结果数量 $skip: ...
- 再探vue
1. vue项目搭建 搭建vue环境需要安装node软件,node是由c++编写而成,主要运行js文件或者js代码的,安装node会自动安装一个管理器叫npm,建议换源下载,国外的网站较慢(比如cnp ...
- Vim升华之树形目录插件NERDTree安装图解(ubuntu)
此文经验证:为真 http://www.linuxidc.com/Linux/2013-06/86048.htm
- asp.net core刷新css缓存
在非spa程序开发的时候.css经常会因为浏览器的缓存机制导致不刷新. 很多前端为了应对这个问题,都会引入webpack或者gulp等工具来处理css缓存的问题. 但是作为一个偏服务器端的程序员来说. ...
- 开发一个带UI的库(asp.net core 3.0)
在GitHub上有个项目,本来是作为自己研究学习.net core的Demo,没想到很多同学在看,还给了很多星,所以觉得应该升成3.0,整理一下,写成博分享给学习.net core的同学们. 项目名称 ...
- springmvc引入静态资源文件
如果web.xml中配置的DispatcherServlet请求映射为“/”, springmvc将捕获web容器所有的请求,当然也包括对静态资源的请求.springmvc会将他们当成一个普通请求处理 ...
- idea 添加 注释 配置
为类添加自动注释模版 File-->Settings-->Editor-->File and Code Templates 启用该模板才有效一定要勾上 /** * @author : ...
- [Quarks PwDump]Hash dump神器
好不好用就不用说了哈 记录下使用方式 也支持导出本地哈希.域控哈希等.配合hashcat神器 奇效. 它目前可以导出 : – Local accounts NT/LM hashes +history ...
- Redis 3.0中文版学习(二)
网址:http://wiki.jikexueyuan.com/project/redis-guide/entry-to-master-middle.html 1.Redis的列表: 采用链表的实现方法 ...