[hgoi#2019/3/3]赛后总结
T1--最长公共前缀(lcp)
定义两个字符串S,T 的最长公共前缀lcp(S,T)为最长的字符串R,满足R 既是S 的前缀又是T 的前缀。
给定一个字符串S,下标从1 开始,每次询问给出四个正整数a,b,c,d,你需要输出[a,b]这个子串与[c,d]这个子串的lcp 的长度。
解法
暴力60分不用说了,那么正解可以用扩展\(kmp\),或者是万能字符串处理方法\(hash\)。但是我不会扩展\(kmp\),所以我就只用\(hash\)来乱搞一下。
那么二分查找这个前缀的长度,每次用\(hash\)检查一下,总的时间复杂度就是\(O(nlogn)\)。
ac代码
# include <cstdio>
# include <cstring>
# include <algorithm>
# include <ctype.h>
# include <iostream>
# include <cmath>
# include <map>
# include <vector>
# include <queue>
# define LL long long
# define ms(a,b) memset(a,b,sizeof(a))
# define ri (register int)
# define inf (0x7f7f7f7f)
# define pb push_back
# define fi first
# define se second
# define pii pair<int,int>
using namespace std;
inline int gi(){
int w=0,x=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return w?-x:x;
}
# define N 100005
const int Mod=1e9+7,Base=127;
LL f[N],hash[N];
int n,m;
char s[N];
LL get_hash(int l,int r){
return (f[r]-f[l-1]*hash[r-l+1]%Mod+Mod)%Mod;
}
int query(int a,int b,int c,int d){
int l=1,r=b-a+1,res=0;
if (d-c+1<r) r=d-c+1;
while (l<=r){
int mid=(l+r)>>1;
if (get_hash(a,a+mid-1)==get_hash(c,c+mid-1)) l=mid+1,res=mid;
else r=mid-1;
}
return res;
}
int main(){
n=gi(),m=gi();
scanf("%s",s+1);
hash[0]=1;
for (int i=1;i<=n;i++) hash[i]=hash[i-1]*(LL)Base%Mod;
for (int i=1;i<=n;i++) f[i]=(f[i-1]*(LL)Base+s[i])%Mod;
while (m--){
int a=gi(),b=gi(),c=gi(),d=gi();
printf("%d\n",query(a,b,c,d));
}
return 0;
}
T2--抢救粮仓(save)
查尔明的家着火啦!他的粮仓正面临着被烧毁的危险!
查尔明在山上一共建有n 个粮仓,按海拔从高到低依次被标记上编号1 到n,且没有任意两个粮仓的海拔是一样的。第i 个粮仓里藏有a[i]吨粮食,第i 个粮仓与第i-1 个粮仓之间的距离为1。
查尔明立马掏出水枪进行灭火,每次灭火他可以指定一个粮仓进行抢救,由于不同粮仓的火势不同,需要喷的水量也不同,抢救第i 个粮仓需要消耗b[i]吨水。查尔明的手速实在是太快了,你可以理解成灭火是瞬间完成的。与此同时,查尔明的助手们开着货车去转移粮食,因为他们认为越低的地方越安全,所以他们只会把粮食从高处运往低处,最终运到某个被灭过火的粮仓。查尔明的粮食很奇怪,每个粮仓都有一个共享值d[i],表示第i 个粮仓只能容纳与距自己距离不超过d[i]的粮仓的粮食,否则就会发生爆炸,所以在运输的过程中务必要避免发生爆炸。
已知水费和粮食运输费都为1 元/吨,查尔明想知道,自己最少需要花费多少钱来抢救全部粮食?
解法
一开始没有想到用dp,就打了一个三个特判。当\(n<=1000\)时,按照从低到高依次遍历,如果可以直接灭掉,那么就直接灭掉,然后再用这个点来更新后面的其他节点,我们更新的就是最小值,在判断。第二种情况是\(d_i=n\),那么也就是所有的节点都可以更新其他的所有节点,那么就暴力取最小值。
但是这只是\(70\)分,那么如果要拿到接下来的30分,我们就需要用\(dp\),\(f[i]\)表示前\(i\)个仓库需要的最小代价。转移方程就是:\(f[i]=min(f[j]-sum[j])+sum[i-1]+b[i](j>=i-d[i]-1)\),这个意思就是可以从\(j\),这个j是在i的范围内,加上他能够带来的代价,再取上最小值。
这个最小值可以用单调队列来维护或者是用树状数组或者是线段树来维护。
ac代码
# include <cstdio>
# include <cstring>
# include <algorithm>
# include <ctype.h>
# include <iostream>
# include <cmath>
# include <map>
# include <vector>
# include <queue>
# define LL long long
# define ms(a,b) memset(a,b,sizeof(a))
# define ri (register int)
# define inf (0x7f7f7f7f)
# define pb push_back
# define fi first
# define se second
# define pii pair<int,int>
using namespace std;
inline int gi(){
int w=0,x=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return w?-x:x;
}
# define N 100005
int q[N],f[N],a[N],b[N],d[N],sum[N];
int n,tail,head;
int find(int x){
int l=head,r=tail-1,res;
while (l<=r){
int mid=(l+r)>>1;
if (q[mid]<x) l=mid+1;
else r=mid-1,res=mid;
}
return q[res];
}
int main(){
n=gi();
for (int i=1;i<=n;i++) a[i]=gi(),sum[i]=sum[i-1]+a[i];
for (int i=1;i<=n;i++) b[i]=gi();
for (int i=1;i<=n;i++) d[i]=gi();
q[tail++]=0;
for (int i=1;i<=n;i++){
int p=find(i-d[i]-1);
f[i]=f[p]-sum[p]+b[i]+sum[i-1];
while (head<tail&&f[q[tail-1]]-sum[q[tail-1]]>=f[i]-sum[i]) tail--;
q[tail++]=i;
}
printf("%d\n",f[n]);
return 0;
}
T3--幸运7(seven)
查尔明为了锻炼自己的观察力,在纸上画了一棵有n 个节点的树,点与点之间通过边连接,每条边有一个正整数权值。查尔明想要用肉眼观察出有多少组(i,j)满足1<=i<j<=n,且i 到j 的距离是他的幸运数7 的倍数。
查尔明不一会儿就观察出来了,但是他不知道自己的答案是否正确,你能写一个程序帮助他检验自己的答案吗?
解法
这道题太水了,原题是聪聪可可,点分治或者是树形dp。
点分治在我的xio讲堂里有讲到过,讲一下如何用树形dp来做。
定义:\(f[i][j]\)表示以第\(i\)为根节点的子树,到根节点距离除以7的余数\(j\)的节点的个数。
转移方程就是:\(f[i][j]=f[son][((j-len)%7+7%7]\),\(son\)是\(i\)节点的儿子,\(len\)是\(i\)到\(son\)之间的长度。
答案\(ans\)需要在递归的时候累加出来,\(ans=f[son][(-j-len)%7]*f[u][j]\),。
ac代码
# include <cstdio>
# include <cstring>
# include <algorithm>
# include <ctype.h>
# include <iostream>
# include <cmath>
# include <map>
# define LL long long
# define ms(a,b) memset(a,b,sizeof(a))
# define ri (register int)
# define inf (0x7f7f7f7f)
# define pb push_back
# define fi first
# define se second
# define pii pair<int,int>
using namespace std;
inline int gi(){
int w=0,x=0;char ch=0;
while(!isdigit(ch)) w|=ch=='-',ch=getchar();
while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return w?-x:x;
}
# define N 100005
struct edge{
int to,nt,w;
}E[N<<1];
LL f[N][7];
int H[N];
int cnt,n;
LL ans;
void addedge(int u,int v,int w){
E[++cnt]=(edge){v,H[u],w}; H[u]=cnt;
}
void dfs(int u,int fa){
f[u][0]=1;
for (int e=H[u];e;e=E[e].nt){
int v=E[e].to,w=E[e].w;
if (v==fa) continue;
dfs(v,u);
for (int i=0;i<7;i++) ans+=f[v][i]*f[u][((-i-w)%7+7)%7]*2;
for (int i=0;i<7;i++) f[u][((i+w)%7+7)%7]+=f[v][i];
}
}
int main(){
n=gi();
for (int i=1;i<n;i++){
int u=gi(),v=gi(),w=gi();
addedge(u,v,w); addedge(v,u,w);
}
ans=0; dfs(1,0);
printf("%lld\n",ans/2);
return 0;
}
[hgoi#2019/3/3]赛后总结的更多相关文章
- [hgoi#2019/3/10]赛后总结
关于本次hg模拟赛,题目来源于CF1110. t1-无意义运算符(meaning) 题目描述 最大公约数和位运算之间有共同点吗?是时候来研究一下了. 给定一个正整数a,请找到一个闭区间[1,a-1] ...
- 「HGOI#2019.4.19省选模拟赛」赛后总结
t1-Painting 这道题目比较简单,但是我比较弱就只是写了一个链表合并和区间DP. 别人的贪心吊打我的DP,嘤嘤嘤. #include <bits/stdc++.h> #define ...
- [hgoi#2019/3/21]NOIP&NOI赛后总结
前言 今天做的是是2010年提高组和NOI的题目,做过几道原题,但是还是爆炸了,我真的太弱了. t1-乌龟棋 https://www.luogu.org/problemnew/show/P1541 这 ...
- [hgoi#2019/2/16t3]psolve
题目描述 Dustar有n道题目要做.他的月薪是m元. 由于题目是一流的难题,所以Dustar不得不找个人来帮(代)助(替)他写作业. 找人写作业不是免费的,但是他们能保证在一个月内做出任何题目.每做 ...
- [hgoi#2019/2/16t2]friend
题目描述 在一个遥远的国度里有n个人,每个人手上写着4个互不相同的数. 这个国度比较奇怪,如果两个人至少有一个数字相同,则他们是一对朋友. 现在这n个人按序号从左到右排成了一排,每个人都想知道在他左边 ...
- [hgoi#2019/2/16t1]math
题目描述 解法 我们稍微枚举一下前面几位,可以得到这样的规律. \[X_i=\frac{1}{2^{i+1}-1}\] \[Y_i=\frac{1}{2^{2^i}-1}\] 那么要使\(xm=yn\ ...
- [hgoi#2019/2/24]玄学考试
感想 对于这次考试,真的不想说什么了,太玄学了!!! t1输出比标准输出长,这是什么操作???难道要关文件???但是交到oj上又A掉了.这是什么操作. t2还好,没有出什么意外...但是要吐槽一下出题 ...
- [hgoi#2019/2/18]比较水
T1--调换纸牌(card) Alex有 n张纸牌,每张纸牌上都有一个值ai,Alex把这些纸牌排成一排,希望将纸牌按值从小到大的顺序排好.现在他把这个任务交给你,你只能进行一种操作:选中一张牌,然后 ...
- [hgoi#2019/2/17t1]million
题目描述 面对格鲁的入侵,小黄人们要组建一支队伍,来抵御进攻,现在有编号为1 至n 的小黄人,任命编号为n 的队长,由其挑选队员,当然编号不是随便编的,每一个编号里都包含一个小黄人的个人信息,现在队长 ...
随机推荐
- 【转】JS中,中国标准时间转化为yyyy-MM-dd
'Thu May 12 2016 08:00:00 GMT+0800 (中国标准时间)'--此格式日期无法传到java后台,须格式化,方法如下 var d = new Date('Thu May 12 ...
- item 12: 把重写函数声明为“override”的
本文翻译自modern effective C++,由于水平有限,故无法保证翻译完全正确,欢迎指出错误.谢谢! 博客已经迁移到这里啦 C++中的面向对象编程总是围绕着类,继承,以及虚函数.这个世界中, ...
- TDD、BDD、ATDD、DDD 软件开发模式
TDD.BDD.ATDD.DDD 软件开发模式 四个开发模式意思: TDD:测试驱动开发(Test-Driven Development) BDD:行为驱动开发(Behavior Driven Dev ...
- 由一个“两次请求”引出的Web服务器跨域请求访问问题的解决方案
http://blog.csdn.net/cnhnnyzhy/article/details/53128179 (4)Access-Control-Max-Age 该字段可选,用来指定本次预检请求的有 ...
- 结对编程 学习手记ver1.2
团队成员: 226 高雅智 164刘浩然: 一 结对编程 辛辛苦苦搞了好久的时间,就是没有人家的快,明明算法都差不多,哎~~~ 结对的优势,在于双方互相督促,对于代码能贡献自己的能力,人多力量 ...
- Scrum Meeting 6
第六次会议 由于之前队员一直在做数据库和编译大作业,课业压力较大,所以软工进度往后拖了好多. No_00:工作情况 No_01:任务说明 待完成 已完成 No_10:燃尽图 N ...
- 同步手绘板——android端下笔后颜色变化
实现效果 : 在设计之初我们以为是改变笔线条的粗细来实现类似效果,后来通过找其他相关软件比对发现是不改变线条的粗细,通过改变透明度实现下笔后颜色的渐变,虽然已实现,但渐变效果很一般,不流畅,算法还待优 ...
- 软件工程——移动的HelloWorld
package disiti; import java.awt.Color; import java.awt.Cursor; import java.awt.Font; imp ...
- 【转】STM32 独立看门狗简介
STM32 的独立看门狗由内部专门的 40Khz 低速时钟驱动,即使主时钟发生故障,它也仍然有效. 看门狗的原理:单片机系统在外界的干扰下会出现程序跑飞的现象导致出现死循环,看门狗电路就是为了避免这种 ...
- MySql连接空闲8小时自动断开引起的问题
一.问题描述 最近遇到了一个奇怪的MySql数据库问题,好几次前一天晚上历史数据还正常存储,第二天早上来了看实时数据存储还正常,历史数据不存储了.找了好久也没找到问题.后来仔细想了想,历史数据设置 ...