题解和总结——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 考虑怎么统计答案, 我场上的思路是统计以一个点作为结尾的最长上升链, 但这显然是很难处理的. 正解的方法是统计以每个点作为折弯点的最长上升链. 具体的内 ...
随机推荐
- 你竟然不装油猴插件-Chrome神器TamperMonkey
油猴插件是一款可以在chrome浏览器中使用油猴脚本的插件.理解为脚本运行的平台 脚本 是一段代码,安装之后,有些脚本能为网站添加新的功能,有些能使网站的界面更加易用,有些则能隐藏网站上烦人的部分内容 ...
- 从零开始入门 K8s | 应用存储和持久化数据卷:存储快照与拓扑调度
作者 | 至天 阿里巴巴高级研发工程师 一.基本知识 存储快照产生背景 在使用存储时,为了提高数据操作的容错性,我们通常有需要对线上数据进行 snapshot ,以及能快速 restore 的能力.另 ...
- 4、pytest 中文文档--pytest-fixtures:明确的、模块化的和可扩展的
目录 1. fixture:作为形参使用 2. fixture:一个典型的依赖注入的实践 3. conftest.py:共享fixture实例 4. 共享测试数据 5. 作用域:在跨类的.模块的或整个 ...
- android设置透明状态栏
先是半透明效果(两种方法): 第一种(简单): //直接将下面的代码放在activity中的setContentView(R.layout.activity_main);中之前就行了 if (Buil ...
- git一步步上传自己的项目至github,及仓库更新
一.使用git上传项目到github 首先登陆github账号,选择新建一个库,填写项目名称,描述 创建完成之后,跳转到下面的页面,下面红框中的网址要记住,在后面上传代码的时候需要使用 接下来,我们需 ...
- bugku web8
打开网站,是一段PHP代码, <?php extract($_GET); if (!empty($ac)) { $f = trim(file_get_contents($fn)); if ($a ...
- Salesforce学习之路-developer篇(四)Visualforce结合Reports展示图表
Salesforce作为一款CRM系统,个人觉得最重要的环境便是在于数据的展示和联动,而Salesforce也本身提供了相当强大的功能,Report在展示图表的方面十分强大,前段时间更是宣布以157亿 ...
- RegExp实现字符替换
将字符串组中的所有Paul替换成Ringo,g:执行全局匹配,查找所有匹配而非在找到第一个匹配后停止;\b:匹配单词边界,划分匹配字符的起始范围 <!DOCTYPE html> <h ...
- DeCantor Expansion (逆康托展开)
Background\text{Background}Background The \text{The }The Listen&Say Test will be hold on May 11, ...
- [JZOJ5778]【NOIP提高A组模拟2018.8.8】没有硝烟的战争
Description 被污染的灰灰草原上有羊和狼.有N只动物围成一圈,每只动物是羊或狼.该游戏从其中的一只动物开始,报出[1,K]区间的整数,若上一只动物报出的数是x,下一只动物可以报[x+1,x+ ...