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]赛后总结的更多相关文章

  1. [hgoi#2019/3/10]赛后总结

    关于本次hg模拟赛,题目来源于CF1110. t1-无意义运算符(meaning) 题目描述 最大公约数和位运算之间有共同点吗?是时候来研究一下了. 给定一个正整数a,请找到一个闭区间[1,a-1] ...

  2. 「HGOI#2019.4.19省选模拟赛」赛后总结

    t1-Painting 这道题目比较简单,但是我比较弱就只是写了一个链表合并和区间DP. 别人的贪心吊打我的DP,嘤嘤嘤. #include <bits/stdc++.h> #define ...

  3. [hgoi#2019/3/21]NOIP&NOI赛后总结

    前言 今天做的是是2010年提高组和NOI的题目,做过几道原题,但是还是爆炸了,我真的太弱了. t1-乌龟棋 https://www.luogu.org/problemnew/show/P1541 这 ...

  4. [hgoi#2019/2/16t3]psolve

    题目描述 Dustar有n道题目要做.他的月薪是m元. 由于题目是一流的难题,所以Dustar不得不找个人来帮(代)助(替)他写作业. 找人写作业不是免费的,但是他们能保证在一个月内做出任何题目.每做 ...

  5. [hgoi#2019/2/16t2]friend

    题目描述 在一个遥远的国度里有n个人,每个人手上写着4个互不相同的数. 这个国度比较奇怪,如果两个人至少有一个数字相同,则他们是一对朋友. 现在这n个人按序号从左到右排成了一排,每个人都想知道在他左边 ...

  6. [hgoi#2019/2/16t1]math

    题目描述 解法 我们稍微枚举一下前面几位,可以得到这样的规律. \[X_i=\frac{1}{2^{i+1}-1}\] \[Y_i=\frac{1}{2^{2^i}-1}\] 那么要使\(xm=yn\ ...

  7. [hgoi#2019/2/24]玄学考试

    感想 对于这次考试,真的不想说什么了,太玄学了!!! t1输出比标准输出长,这是什么操作???难道要关文件???但是交到oj上又A掉了.这是什么操作. t2还好,没有出什么意外...但是要吐槽一下出题 ...

  8. [hgoi#2019/2/18]比较水

    T1--调换纸牌(card) Alex有 n张纸牌,每张纸牌上都有一个值ai,Alex把这些纸牌排成一排,希望将纸牌按值从小到大的顺序排好.现在他把这个任务交给你,你只能进行一种操作:选中一张牌,然后 ...

  9. [hgoi#2019/2/17t1]million

    题目描述 面对格鲁的入侵,小黄人们要组建一支队伍,来抵御进攻,现在有编号为1 至n 的小黄人,任命编号为n 的队长,由其挑选队员,当然编号不是随便编的,每一个编号里都包含一个小黄人的个人信息,现在队长 ...

随机推荐

  1. phpstorm 2018.1.2的安装和破解

    1.什么是phpstorm? PhpStorm是一个轻量级且便捷的PHP IDE,其旨在提高用户效率,可深刻理解用户的编码,提供智能代码补全,快速导航以及即时错误检查.但是phpstorm是商业软件, ...

  2. FreeRTOS 任务与调度器(2)

    在上一篇我们介绍了FreeRTOS任务的一些基本操作和功能,今天我们会介绍一个很好很强大的功能——任务通知 任务通知可以在不同任务之间传递信息,它可以取代二值信号量.计数信号量.事件标志组.深度为1的 ...

  3. win10系统安装web3js的正确方法(2)

    信渤网络科技是一家基于互联网信息服务的区块链技术公司,专业提供区块链技术培训,智能合约定制开发,文字图片数据存证上链等服务,为相关企业提供区块链应用落地项目的技术方案 崇尚代码即法律,做一个智能合约开 ...

  4. zifutongji

    第三次作业要求我们自己写程序,我算我们班写的比较晚的了,我听他们写的都是在文件中写一段代码,然后读出来.我们班大部分都是,所以,我就想可不可以跟他们不一样呢,写一个属于自己的思路. 所以我想到了数组. ...

  5. 第三个Sprint冲刺第四天(燃尽图)

  6. asp.net webform设计思路的思考

    我使用asp.net的webform框架进行web应用程序的开发已经差不多四年了,在整个开发生涯中,也使用过一年asp.net的mvc框架.因为网上经常有讨论webform框架和mvc框架的优劣,所以 ...

  7. 2017BUAA软工第0次作业

    第一部分:结缘计算机 1. 你为什么选择计算机专业?你认为你的条件如何?和这些博主比呢? 我在上大学之前,其实一直就没怎么考虑过自己以后想要选什么专业,只知道一个大致的方向一定是理工科.毕竟大学之前, ...

  8. Installing and removing VNC Connect | Red Hat | VNC Connect

    https://www.realvnc.com/en/connect/docs/redhat-install-remove.html 此软件会和TigerVNC(Server)或者X11VNC Ser ...

  9. jstack 使用一例

    31jstack -m -F 2340 >libra.log 2>&1 jstack -m -F 2340 >libra2.log 2&>1 jstack -m ...

  10. Vue的router使用

    <div id="app"> <router-link to="/home">home</router-link> < ...