题解和总结——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 考虑怎么统计答案, 我场上的思路是统计以一个点作为结尾的最长上升链, 但这显然是很难处理的. 正解的方法是统计以每个点作为折弯点的最长上升链. 具体的内 ...
随机推荐
- [ASP.NET Core 3框架揭秘] 跨平台开发体验: Windows [上篇]
微软在千禧年推出 .NET战略,并在两年后推出第一个版本的.NET Framework和IDE(Visual Studio.NET 2002,后来改名为Visual Studio),如果你是一个资深的 ...
- Nginx+Tomcat Https SSL部署方案
1.软件版本: nginx-1.15+ tomcat-8.0+ 2.先解决一个疑问:Tomcat到底需不需要配置SSL? 答案:不需要 3.SSL申请 使用腾讯云.阿里云的服务器,会更加方便申请.(申 ...
- Spark 学习笔记之 Streaming Window
Streaming Window: 上图意思:每隔2秒统计前3秒的数据 slideDuration: 2 windowDuration: 3 例子: import org.apache.kafka.c ...
- 『开发技术』Ubuntu与Windows如何查看CPU&GPU&内存占用量
0 序·简介 在使用Ubuntu或者Windows执行一些复杂数据运算时,需要关注下CPU.GPU以及内存占用量,如果数据运算超出了负荷,会产生难以预测的错误.本文将演示如何用简单地方式,实时监控Ub ...
- Delphi Tips
Delphi Tips 函数篇 语法篇 函数篇 StrToDate() function StrToDate(const S: string): TDateTime; function StrToDa ...
- HTML5存储--离线存储
离线存储技术 HTML5提出了两大离线存储技术:localstorage与Application Cache,两者各有应用场景:传统还有离线存储技术为Cookie. 经过实践我们认为localstor ...
- markdown下载、安装、破解、汉化与常用语法
markdown是一种纯文本格式的标记语言.通过简单的标记语法,它可以使普通文本内容具有一定的格式. 一.markdown下载 markdown破解版下载地址: http://www.pc6.com/ ...
- Uber Go 语言编程规范
目录 Uber Go 语言编程规范 1. 介绍 2. 编程指南 3. 性能相关 4. 编程风格 5. 编程模式(Patterns) 6. 总结 Uber Go 语言编程规范 相信很多人前两天都看到 U ...
- Windows系统调用中的现场保存
Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html Windows系统调用中的现场保存 我们之前介绍过三环进零环的步骤 ...
- Webshell免杀绕过waf
转自圈子404师傅 0x01 前言# 尽最大努力在一文中让大家掌握一些有用的WEBSHELL免杀技巧 0x02 目录# 关于eval 于 assert 字符串变形 定义函数绕过 回调函数 回调函数变形 ...