首页 > HGOI 20190709 题解

HGOI 20190709 题解

Problem A 紫色激情

一个序列${a_n}$,求出方差最大的子序列。

其中方差 [l,r] 的定义是$S^2 = frac{1}{n} sumlimits_{i=l}^{r} (x_i-ar{x})^2$

对于100%的数据满足$n leq 10^3$

Sol : 直接推一波公式就可以前缀和优化了。

  ${ S_{l,r} }^2 = -ar{x}^2 +frac{sum_{i=l}^r {x_i}^2}{n}$

      时间复杂度$O(n^2)$

# include
# define int long long
using namespace std;
const int N=2e3+10;
int s1[N],s2[N];int n;
inline int read()
{int X=0,w=0; char c=0;while(c<'0'||c>'9') {w|=c=='-';c=getchar();}while(c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar();return w?-X:X;
}
inline void write(int x)
{if (x<0) x=-x,putchar('-'); if (x>9) write(x/10);putchar(x%10+'0');
}
signed main()
{n=read();for (int i=1;i<=n;i++) {int t=read(); s1[i]=s1[i-1]+t;s2[i]=s2[i-1]+t*t;}double ans=-1e9; int ansl=0,ansr=0;for (int l=1;l<=n;l++)for (int r=l;r<=n;r++) {double t=-(double)(s1[r]-s1[l-1])*(s1[r]-s1[l-1])/(double)(r-l+1)/(double)(r-l+1);double w=(double)(s2[r]-s2[l-1])/(double)(r-l+1); if (t+w>ans) { ans=t+w; ansl=l; ansr=r;}}write(ansl);putchar(' ');write(ansr); putchar('
');return 0;
}
passion.cpp

Problem B 克罗地亚狂想曲

共有$n$个节点,从每个节点可以向前面一个节点连一条边,而如果和后面一个节点的连边将被忽略。

两个相连节点之间有一条连边,可以直接经过,找出一条访问的路径,使得每个节点被经过最多2次,

经过路径上点值之和最大。

对于100%的数据 , $n leq 3 imes 10^5 $

Sol: 显然,向前连边的这个过程是没有后效性的,所以可以进行动态规划。

  而每个节点最多只能被经过2次保证了一次转移的合法性。

  设$f_i$表示走到节点$i$时候最大值。

  如果当前元素没有向前连边,那么答案就从上一节点走来,$f_i = f_{i-1} + a_i$

  如果当前元素有向前连边到$j$那么可以考虑从$j$过来在经过$j$,在走到$i$,再接下去走。

  这等价于$j->i$的路径被累加了$2$次,那么转移方程就是$f_i = f_{j-1}  + 2 sumlimits_{k=j}^{i} a_k$

  然后那个$sum$累加可以用前缀和优化掉,这样这个DP就是线性的了。

  复杂度$O(n)$

# include 
# define int long long
using namespace std;
const int N=3e5+10;
int from[N],f[N],s[N],n;
inline int read()
{int X=0,w=0; char c=0;while(c<'0'||c>'9') {w|=c=='-';c=getchar();}while(c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar();return w?-X:X;
}
inline void write(int x)
{if (x<0) x=-x,putchar('-'); if (x>9) write(x/10);putchar(x%10+'0');
}
signed main()
{n=read();for (int i=1;i<=n;i++) {int t=read();if (t>i) continue;from[i]=t;}for (int i=1;i<=n;i++) {int t=read();s[i]=s[i-1]+t;}for (int i=1;i<=n;i++) {f[i]=f[i-1]+s[i]-s[i-1];if (from[i]!=0) f[i]=max(f[from[i]-1]+2*(s[i]-s[from[i]-1]),f[i]);}write(f[n]);putchar('
'); return 0;
}
rhapsody.cpp

Problem C 花之舞

给出一个字符串中,求该字符串中最大不重复双倍回文串覆盖。

对于100%的数据,$ len(s) leq 10^3 $ 

Sol :  首先我们可以通过字符串Hash的做法判定一个串是不是回文串,这样只需要一遍$O(n)$的预处理,再$O(1)$判定即可。

然后我们可以$O(n^2)$枚举从$i$开始的所有双倍回文串,然后可以使用类似线段覆盖的DP做出最大不重复双倍回文串覆盖。

最终的复杂度是$O(n^2)$的。

# include
# define int long long
using namespace std;
const int mo=1e9+7;
const int base=131;
const int N=1e3+10;
int p[N],a[N],hash1[N],hash2[N],f[N];
int n;
vector<int>v[N];
inline int read()
{int X=0,w=0; char c=0;while(c<'0'||c>'9') {w|=c=='-';c=getchar();}while(c>='0'&&c<='9') X=(X<<3)+(X<<1)+(c^48),c=getchar();return w?-X:X;
}
inline void write(int x)
{if (x<0) x=-x,putchar('-'); if (x>9) write(x/10);putchar(x%10+'0');
}
int gethash(int num,int l,int r)
{if (num==1) return ((hash1[r]-hash1[l-1]*p[r-l+1]%mo)%mo+mo)%mo;else return ((hash2[r]-hash2[l-1]*p[r-l+1]%mo)%mo+mo)%mo;
}
bool check(int l,int r)
{if ((r-l+1)&1) {int pos=(l+r)/2,len=(r-l)/2;        if (gethash(1,pos,pos+len)==gethash(2,n+1-pos,n+1-pos+len)) return 1;else return 0;} else {int pos1=(l+r)/2,pos2=pos1+1,len=(r-l-1)/2;if (gethash(1,pos2,pos2+len)==gethash(2,n+1-pos1,n+1-pos1+len)) return 1;else return 0;}
}
void fun(int pos)
{for (int mid=(n+1-pos)/2;mid>=1;mid--) if (check(pos,pos+mid-1)&&check(pos+mid,pos+2*mid-1)&&gethash(1,pos,pos+mid-1)==gethash(1,pos+mid,pos+2*mid-1)) v[pos].push_back(pos+2*mid-1);
}
signed main()
{
//    freopen("dance.in","r",stdin);
//    freopen("dance.out","w",stdout);n=read(); p[0]=1;for (int i=1;i<=n;i++) a[i]=read(),p[i]=p[i-1]*base%mo;    for (int i=1;i<=n;i++) hash1[i]=(hash1[i-1]*base%mo+a[i])%mo;int u=0;    for (int i=n;i>=1;i--) u++,hash2[u]=(hash2[u-1]*base%mo+a[i])%mo;for (int i=1;i<=n;i++) fun(i); for (int i=n;i>=1;i--) {f[i]=f[i+1];for (int j=0;j)f[i]=max(f[i],f[v[i][j]+1]+(v[i][j]-i+1));}write(f[1]); putchar('
');return 0;
} 
dance.cpp

 

转载于:https://www.cnblogs.com/ljc20020730/p/11156950.html

更多相关:

  •         Apache POI是一个开源的利用Java读写Excel,WORD等微软OLE2组件文档的项目。        我的需求是对Excel的数据进行导入或将数据以Excel的形式导出。先上简单的测试代码:package com.xing.studyTest.poi;import java.io.FileInputSt...

  • 要取得[a,b)的随机整数,使用(rand() % (b-a))+ a; 要取得[a,b]的随机整数,使用(rand() % (b-a+1))+ a; 要取得(a,b]的随机整数,使用(rand() % (b-a))+ a + 1; 通用公式:a + rand() % n;其中的a是起始值,n是整数的范围。 要取得a到b之间的...

  • 利用本征图像分解(Intrinsic Image Decomposition)算法,将图像分解为shading(illumination) image 和 reflectance(albedo) image,计算图像的reflectance image。 Reflectance Image 是指在变化的光照条件下能够维持不变的图像部分...

  • 题目:面试题39. 数组中出现次数超过一半的数字 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字。 你可以假设数组是非空的,并且给定的数组总是存在多数元素。 示例 1: 输入: [1, 2, 3, 2, 2, 2, 5, 4, 2] 输出: 2 限制: 1 <= 数组长度 <= 50000 解题: cl...

  • 题目:二叉搜索树的后序遍历序列 输入一个整数数组,判断该数组是不是某二叉搜索树的后序遍历结果。如果是则返回 true,否则返回 false。假设输入的数组的任意两个数字都互不相同。 参考以下这颗二叉搜索树:      5     /    2   6   /  1   3示例 1: 输入: [1,6,3,2,5] 输出...

  • #include #include #include #include #include #include #include

  • 题目:表示数值的字符串 请实现一个函数用来判断字符串是否表示数值(包括整数和小数)。例如,字符串"+100"、"5e2"、"-123"、"3.1416"、"0123"及"-1E-16"都表示数值,但"12e"、"1a3.14"、"1.2.3"、"+-5"及"12e+5.4"都不是。 解题: 数值错误的形式有多种多样,但是正确的...

  • 加法伺候  //超过20位数值相加---------------------------------------- function bigNumAdd(a, b) {if (!(typeof a === "string" && typeof b === "string")) return console.log("传入参数必...

  • 业务场景: 从中文字句中匹配出指定的中文子字符串 .这样的情况我在工作中遇到非常多, 特梳理总结如下. 难点: 处理GBK和utf8之类的字符编码, 同时正则匹配Pattern中包含汉字,要汉字正常发挥作用,必须非常谨慎.推荐最好统一为utf8编码,如果不是这种最优情况,也有酌情处理. 往往一个具有普适性的正则表达式会简化程...

  • 简单record 一下 #include // 'struct sockaddr_in' #include #include // 'struct ifreq' and 'struct if_nameindex' #include #inc...

  • 用python编写乘法口诀表的方法 发布时间:2020-08-25 11:46:35 来源:亿速云 阅读:60 作者:小新 用python编写乘法口诀表的方法?这个问题可能是我们日常学习或工作经常见到的。希望通过这个问题能让你收获颇深。下面是小编给大家带来的参考内容,让我们一起来看看吧! 第一种:使用for遍历循环嵌套for x in...

  • //很长一段时间我都只使用以下方式做数组循环,具体原因看数据 var aa = for (var i = 0, l = aa.length; i < l; i++) { var a = aa[i];} 数据采集图片来源于网友 很明显,for循环第二种方式完胜!!! 至于for in、forEach什么的,不知道甩他们多少...

  • 目录 1. Scene Graph Generation with External Knowledge and Image Reconstruction 2. Knowledge Acquisition for Visual Question Answering via Iterative Querying Author...

  • 基础题1: 输入一个正整数 n (1≤n≤10)和n 阶方阵a的元素,如果方阵a中的所有元素都沿主对角线对称,输出“Yes”, 否则,输出“No”。主对角线为从矩阵的左上角至右下角的连线,方阵a中的所有元素都沿主对角线对称指对所有i, k,a[i][k]和a[k][i]相等。输入输出示例如下: 输入: 3 1 2 3 4 5 6 7...

  • 程序流程控制 分支 顺序 循环 if switch&case 1 2 3 调整 break 1.6 前 switch(byte、short、char、int) 1.7 可放String 循环 while(次数不确定) do while for(确定次数) break(跳出本层循环) continue(跳出本次循环)     *   2...