喵哈哈村的魔法考试 Round #15 (Div.2) 题解
哗啦啦村的奇迹果实(一)
题解:显然答案就是最大值减去最小值。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
int n,a[maxn];
int main(){
while(cin>>n){
int x;scanf("%d",&x);
int Mx = x;
int Mi = x;
for(int i=1;i<n;i++){
scanf("%d",&x);
Mx = max(Mx,x);
Mi = min(Mi,x);
}
cout<<Mx-Mi<<endl;
}
}
哗啦啦村的奇迹果实(二)
题解:虽然0可以与其他位置交换,但是0不改变其他数字的相对位置,所以只要找到相对位置,然后进行匹配即可。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 200005;
int a[maxn],b[maxn],tot1,tot2,n;
int solve(){
tot1=0;
tot2=0;
for(int i=0;i<n;i++)
{
int x;scanf("%d",&x);
if(x==0)continue;
a[tot1++]=x;
}
for(int i=0;i<n;i++)
{
int x;scanf("%d",&x);
if(x==0)continue;
b[tot2++]=x;
}
int s=0;
for(int i=0;i<tot2;i++)
{
if(b[i]==a[0])
{
s=i;
break;
}
}
if(tot1!=tot2){
return puts("NO");
}
for(int i=0;i<tot1;i++)
if(a[i]!=b[(i+s)%(tot2)])
return puts("NO");
return puts("YES");
}
int main()
{
while(cin>>n)solve();
}
哗啦啦村的奇迹果实(三)
题解:动态规划。
f[i][j][0]表示当前小象位于格子(i,j)且上一个位置是(i-1,j)所看见的老鼠的最少数量。
f[i][j][1]表示当前小象位于格子(i,j)且上一个位置是(i,j-1)所看见的老鼠的最少数量。
f[i][j][0]=min(f[i-1][j][0]+a[i][j-1],f[i-1][j][1])+a[i+1][j]+a[i][j+1]
f[i][j][1]=min(f[i][j-1][0],f[i][j-1][1]+a[i-1][j])+a[i+1][j]+a[i][j+1]
answer=min(f[n][m][0],f[n][m][1])。
复杂度为 O(NM)。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define N 1100
using namespace std;
int n,m;
int f[N][N];
int g[N][N];
int a[N][N];
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
scanf("%d",&a[i][j]);
memset(f,0x3f,sizeof(f));
memset(g,0x3f,sizeof(g));
f[1][1]=g[1][1]=a[1][1]+a[1][2]+a[2][1];
for(int i=1;i<=n;i++)
{
for(int j=1;j<=m;j++)
{
if(j-1>0)
f[i][j]=min(f[i][j],min(f[i][j-1]+a[i-1][j]+a[i][j+1]+a[i+1][j],g[i][j-1]+a[i][j+1]+a[i+1][j]));
if(i-1>0)
g[i][j]=min(g[i][j],min(f[i-1][j]+a[i][j+1]+a[i+1][j],g[i-1][j]+a[i][j-1]+a[i][j+1]+a[i+1][j]));
}
}
printf("%d\n",min(f[n][m],g[n][m]));
}
哗啦啦村的奇迹果实(四)
算法:最短路。
将“如果城市 B 愿意与城市 A 建立合作关系,当且仅当对于所有满足 d(A,C)<=d(A,B)的城市
C,都有 R(C)<=R(B)。”这一条件转化为“如果城市 B 愿意与城市 A 建立合作关系,当且仅当
对于所有满足 R(C)>R(B)的城市 C,都有 d(A,C)>d(A,B)。”
我们倒序枚举 R 的值 r,然后枚举 R(X)=r 的点 X,以每个点为起点对原图做最短路。设 lim[i]
表示所有点 K(R(K)>R(X))中到点 i 的最小距离,设 dist[i]表示 X 到 i 的最短路。对于点 i,在最
短路过程中,如果 dist[i]>=lim[i],那么表示比 X 的 R 值大的某个点到点 i 的最短距离要比 X
到 i 的距离短,所以 i 不会与 X 建立合作关系,而且不会用 dist[i]去更新其它点的最短路了。
因此,一个点用来更新其它点的条件是 dist[i]<lim[i],此时答案+1,因为答案<=30N,所以总
的更新次数不会超过 30N 次。所以最后复杂度为 O(kNlogN),k 为常数。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<ctime>
using namespace std;
const int INF=0x3f3f3f3f;
const int N=30010,M=300100;
int n,m,nowRank;
int head[N],key[M],Next[M],len[M],cnt;
int Rank[N],dis[N],lim[N],minr[N];
int stack[N],tp;
int top,ans;
struct Heap
{
int x,w;
Heap(void){}
Heap(int _x,int _w):x(_x),w(_w){}
}heap[10*M];
void add(int x,int y,int z)
{
Next[++cnt]=head[x];
key[cnt]=y;
len[cnt]=z;
head[x]=cnt;
}
inline bool cmp(const Heap &a,const Heap &b)
{
if(a.w!=b.w) return a.w>b.w;
else return Rank[a.x]<Rank[b.x];
}
void dijk()
{
while(top)
{
Heap sta=heap[1];
pop_heap(heap+1,heap+top+1,cmp);
top--;
if(sta.w!=dis[sta.x]) continue;
stack[++tp]=sta.x;
for(int i=head[sta.x];~i;i=Next[i])
{
if(Rank[key[i]]>nowRank) continue;
if(dis[key[i]]>sta.w+len[i]&&lim[key[i]]>sta.w+len[i])
{
dis[key[i]]=sta.w+len[i];
heap[++top]=Heap(key[i],dis[key[i]]);
push_heap(heap+1,heap+top+1,cmp);
}
}
}
}
int main()
{
memset(head,-1,sizeof head);
memset(dis,0x3f,sizeof dis);
memset(lim,0x3f,sizeof lim);
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&Rank[i]);
for(int i=1,x,y,z;i<=m;i++)
scanf("%d%d%d",&x,&y,&z),add(x,y,z),add(y,x,z);
for(int i=10;i>=1;i--)
{
nowRank=i;
memset(minr,0x3f,sizeof minr);
for(int j=1;j<=n;j++)
if(Rank[j]==i)
{
heap[++top]=Heap(j,0);
dis[j]=0;
dijk();
for(;tp;tp--)
{
int k=stack[tp];
if(lim[k]>dis[k]) ans++;
minr[k]=min(minr[k],dis[k]);
dis[k]=INF;
}
}
for(int j=1;j<=n;j++)
lim[j]=min(minr[j],lim[j]);
}
cout<<ans<<endl;
return 0;
}
哗啦啦村的奇迹果实(五)
算法:字符串 hash
枚举两段的长度 len 和第一段的起点 i,我们定义 L 为第一段与第二段的最长公共后缀,当
L>=len 的时候答案+1,而起点为 i+1 时 L 的大小仅仅取决于起点为 i 时 L 大小和 a[i+len]与
a[i+2len+F]的相等关系:
L[i+1] = L[i] + 1 (a[i+len]=a[i+2len+F])
L[i+1] = 0 (a[i+len]!=a[i+2*len+F])
这样朴素的枚举 len 后扫描整个序列是 N^2 的,我们考虑优化这个算法。
首先枚举两段的长度 len,然后我们在递推的时候可以发现,在长度为 len 时,我们没有必
要一格一格的递推,而可以每次向右递推 len 格。我们不妨设第一段的末尾位置为 i,第二
段的末尾位置为 j,设 frontL 表示 a[i+1]„a[i+len]与 a[j+1]„a[j+len]的最长公共前缀,设 backL
表示 a[i+1]„a[i+len]与 a[j+1]„a[j+len]的最长公共后缀,令 L 表示当前的最长公共后缀。
下面分两种情况考虑对于答案的贡献:
情况一:如果 L>=len,ans+=frontL。
情况二:反之,ans+=max(0,L+frontl-i+1)。
下面分两种情况考虑递推后的最长公共后缀 nL:
情况一:如果 a[i+1]„a[i+len]与 a[j+1]„a[j+len]整段相同,nL=L+len。
情况二:反之,nL=backl。
这样对于每个长度 len,需要递推 N/len 次,每次采用 hash+二分的方法 O(logN)的计算最长
公共前/后缀,总的复杂度为 O(NlnNlogN)。
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<ctime>
using namespace std;
typedef long long ll;
typedef unsigned int ull;
const int N=1000010;
const ull mul=133331;
ll ans;
int n,m,k;
int b[N],a[N];
int X[N];
ull Hash[N];
ull f[N]={1};
inline int bin(int x)
{
int l=1,r=k;
while(l<=r)
{
int mid=l+r>>1;
if(b[mid]<=x) l=mid+1;
else r=mid-1;
}
return r;
}
inline ull getHash(const int &l,const int &r)
{
return Hash[r]-Hash[l-1]*f[r-l+1];
}
inline int lcp(int x,int y)
{
int l=0,r=min(n-x+1,n-y+1);
while(l<=r)
{
int mid=l+r>>1;
if(getHash(x,x+mid-1)==getHash(y,y+mid-1)) l=mid+1;
else r=mid-1;
}
return r;
}
inline int anti_lcp(int x,int y)
{
int l=0,r=min(x,y);
while(l<=r)
{
int mid=l+r>>1;
if(getHash(x-mid+1,x)==getHash(y-mid+1,y)) l=mid+1;
else r=mid-1;
}
return r;
}
int main()
{
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
X[i]=a[i];
}
sort(X+1,X+n+1);
X[0]=~0U>>1;
for(int i=1;i<=n;i++)
if(X[i]!=X[i-1])
b[++k]=X[i];
for(int i=1;i<=n;i++)
a[i]=bin(a[i]);
for(int i=1;i<=n;i++) f[i]=f[i-1]*mul;
for(int i=1;i<=n;i++) Hash[i]=Hash[i-1]*mul+a[i];
for(int i=1;2*i+m<=n;i++)
{
int nowl=0;
for(int j=1;;)
{
int len=min(i,n-(j+i+m-1));
if(!len) break;
int frontl=lcp(j,j+i+m);
int backl=anti_lcp(j+len-1,j+m+i+len-1);
frontl=min(frontl,len);
backl=min(backl,len);
if(frontl==len)
{
if(nowl>=i) ans+=len;
else ans+=max(0,nowl+frontl-i+1);
nowl+=len;
}
else
{
if(nowl>=i) ans+=frontl;
else ans+=max(0,nowl+frontl-i+1);
nowl=backl;
}
j+=len;
}
}
cout<<ans<<endl;
return 0;
}
喵哈哈村的魔法考试 Round #15 (Div.2) 题解的更多相关文章
- 喵哈哈村的魔法考试 Round #2 (Div.2) 题解
喵哈哈村的魔法考试 Round #2 (Div.2) 题解 A.喵哈哈村的战争 题解: 这道题就是for一遍,统计每个村子的战斗力的和,然后统计哪个村子的战斗力和大一点就好了. 唯一的坑点,就是这道题 ...
- 喵哈哈村的魔法考试 Round #1 (Div.2) 题解
喵哈哈村的魔法考试 Round #1 (Div.2) 题解 特别感谢出题人,qscqesze. 也特别感谢测题人Xiper和CS_LYJ1997. 没有他们的付出,就不会有这场比赛. A 喵哈哈村的魔 ...
- 喵哈哈村的魔法考试 Round #7 (Div.2) 题解
喵哈哈村的魔法考试 Round #7 (Div.2) 注意!后四道题来自于周日的hihocoder offer收割赛第九场. 我建了个群:欢迎加入qscoj交流群,群号码:540667432 大概作为 ...
- 喵哈哈村的魔法考试 Round #1 (Div.2) 题解&源码(A.水+暴力,B.dp+栈)
A.喵哈哈村的魔法石 发布时间: 2017年2月21日 20:05 最后更新: 2017年2月21日 20:06 时间限制: 1000ms 内存限制: 128M 描述 传说喵哈哈村有三种神 ...
- 喵哈哈村的魔法考试 Round #19 (Div.2) 题解
题解: 喵哈哈村的魔力源泉(1) 题解:签到题. 代码: #include<bits/stdc++.h> using namespace std; int main(){ long lon ...
- 喵哈哈村的魔法考试 Round #14 (Div.2) 题解
喵哈哈村的四月半活动(一) 题解: 唯一的case,就是两边长度一样的时候,第三边只有一种情况. #include <iostream> #include <cstdio> # ...
- 喵哈哈村的魔法考试 Round #4 (Div.2) 题解
有任何疑问,可以加我QQ:475517977进行讨论. A 喵哈哈村的嘟嘟熊魔法(1) 题解 这道题我们只要倒着来做就可以了,因为交换杯子是可逆的,我们倒着去模拟一遍就好了. 有个函数叫做swap(a ...
- 喵哈哈村的魔法考试 Round #20 (Div.2) 题解
题解: A 喵哈哈村的跳棋比赛 题解:其实我们要理解题意就好了,画画图看看这个题意.x<y,那么就交换:x>y,那么x=x%y. 如果我们经过很多次,或者y<=0了,那么就会无限循环 ...
- 喵哈哈村的魔法考试 Round #18 (Div.2) 题解
喵哈哈村的古怪石碑(一) 题解:暴力check一下是等比数列还是等差数列,然后输出答案即可.注意如果数据范围是1e9的话,就要快速幂了. 代码: #include <cstdio> #in ...
随机推荐
- 【bzoj1901】dynamic ranking(带修改主席树)
传送门(权限) 传送门(非权限) 花了一晚上总算把代码调好了……才知道待修改主席树怎么操作…… 然而还是一知半解orz…… 先说说我的理解吧 我们一般建主席树的时候都是直接在序列上建的 但是如果有修改 ...
- 使用python命令构建最简单的web服务
可以使用python自带的包建立最简单的web服务器,使用方法: 1)切换到服务器的根目录下 2)输入命令: python -m SimpleHTTPServer 3)使用wget或者在浏览器访问测试 ...
- mysql通过centos本地命令行还原数据库出现乱码问题
将sql文件上传到centos系统中,还原mysql数据库,发现是乱码 mysql -h10.11.8.62 -uroot -p dbtest </data/dbsql/dbtest.sql 数 ...
- 用java实现邮件发送验证码
java实现邮件发送验证码 建议不要用qq邮箱,我使用qq邮箱直接一直给我报530错误,我一直认为我代码写的有错误或者POP3/SMTP服务没弄好.所以建议注册个别的邮箱,我就申请了个网易163邮箱瞬 ...
- Java内存泄漏问题
1:java中垃圾回收机制主要完成下面两件事情: 跟踪并监控每个java对象,当某个对象处于不可达状态时,回收该对象所占的内存 清理内存分配,回收过程中产生的内存碎片 2:对于JVM的垃圾回收机制来说 ...
- 为什么js中0.1+0.2不等于0.3,怎样处理使之相等?(转载)
为什么js中0.1+0.2不等于0.3,怎样处理使之相等? console.log(0.1+0.2===0.3)// true or false?? 在正常的数学逻辑思维中,0.1+0.2=0.3这个 ...
- 【splunk】数据输入-文件目录 导入失败
今天用splunk的“数据输入-文件目录”自动监控文件并索引,结果失败了,完全没有出现我要的索引. 解决: 删除文件监控 改为一次性索引 再重新添加连续监控 原因: 尚不明确 https://answ ...
- 多行文字溢出[...]的实现(text-overflow: ellipsis)
声明:此文章为转载(点击查看原文),如有侵权24小时内删除.联系QQ:1522025433. 对于单行文字, 很简单.(详见css3产考手册 进入) css: .oneLine { width: 20 ...
- 设计原则:开-闭原则(Open-Closed Principle, OCP)
开-闭原则就是软件实体应当对扩展开放,对修改关闭.(Software entities should be open for extension,but closed for modification ...
- B 找规律
Description 对于正整数n,k,我们定义这样一个函数f,它满足如下规律f(n,k=1)=-1+2-3+4-5+6...nf(n,k=2)=-1-2+3+4-5-6...nf(n,k=3)=- ...