当前位置: 首页 > wzjs >正文

深圳禅城网站设计软件工程与项目管理

深圳禅城网站设计,软件工程与项目管理,坪山做网站的公司,企业推广文案线上同步赛链接 最近有点堕落,在捣鼓一个 b o t bot bot。然后实验室管事老师硬性要求所有实验室成员必须打这个线上赛,就随便签了一下到就润了。但是事后感觉这场 A A A 还真不错,遂回来写一篇题解。感觉每次打比赛都能遇上两个好题&…

线上同步赛链接

最近有点堕落,在捣鼓一个 b o t bot bot。然后实验室管事老师硬性要求所有实验室成员必须打这个线上赛,就随便签了一下到就润了。但是事后感觉这场 A A A 还真不错,遂回来写一篇题解。感觉每次打比赛都能遇上两个好题,真是学无止境啊。


A 出勤规划

思路:

算是撞在我的好球区了,两眼秒了。这个题需要对 d i j k s t r a dijkstra dijkstra p r i m prim prim 算法思想的原理理解透彻,然后把这两个算法的思想结合起来。

d i j k s t r a dijkstra dijkstra 的主要思想是每次选取距离源点最近的点,并通过这个点尝试对其他点的距离进行松弛。核心代码如下:

struct Edge{int v,w;
};
vector<Edge> e[maxn];
struct Node{int u,dis;bool operator<(const Node a)const{return dis>a.dis;}
};
priority_queue<Node> h;int d[maxn];
void dijkstra(int root){for(int i=1;i<=n;i++)d[i]=inf;d[root]=0;h.push({root,d[root]});while(!h.empty()){auto [u,dist]=h.top();h.pop();if(dist>d[u])continue;for(auto [v,w]:e[u]){if(d[u]+w<d[v]){d[v]=d[u]+w;h.push({v,d[v]});}}}
}

有些写法里有的会带上一个 v i s vis vis 数组,用来标记某个点是否已经访问过了。不过这里可以不写,因为可以保证取过的点一定不会被再次松弛了。

朴素的 d i j k s t r a dijkstra dijkstra 中,每次取出一个点,这个点(到源点)的距离就固定了,以后都不可能再变。因为当前堆中存在的点的距离都比当前取出的点的距离要大,同时这个图还不存在负环,这意味着你无论通过什么点,走什么路径,当你回到这个点的时候,距离一定不可能现在的距离要小了。因此你只需要每个点各取出过一次,单源最短路就算完了。

我一直觉得 d i j k s t r a dijkstra dijkstra 是一个动态规划问题,只不过它松弛的策略很聪明,能快速地进行剪枝,不需要枚举全部可能的转移。对于一些 d i j k s t r a dijkstra dijkstra 的变种问题,如果你以动态规划的思路去想,就会比较容易理解(一般都是每个点再开上一两维,以准确描述状态)。所以对变种问题,某个状态第一次从堆中取出它的时候,距离就确定了,性质依然成立。

一个 d i j k s t r a dijkstra dijkstra 变种题:Codeforces Round 918 (Div. 4) G. Bicycles


同理再来看看 p r i m prim prim 算法。它的思想是每次选取距离生成树最近的点,并通过这个点尝试对其他点的距离进行松弛。核心代码如下:

struct Edge{int v,w;
};
vector<Edge> e[maxn];
struct Node{int u,dis;bool operator<(const Node a)const{return dis>a.dis;}
};
priority_queue<Node> h;int d[maxn],ans;
bool vis[maxn];
void prim(int root){for(int i=1;i<=n;i++)d[i]=inf;d[root]=0;h.push({root,d[root]});while(!h.empty()){auto [u,dist]=h.top();h.pop();if(vis[u])continue;else vis[u]=true;for(auto [v,w]:e[u]){if(!vis[v] && w<d[v]){d[v]=w;h.push({v,d[v]});}}}
}

大体上没什么变化,除了多了一个 v i s vis vis 数组和判断条件。这里需要写 v i s vis vis 是因为不能保证取过的点不会被再次松弛。

判断条件变化是因为我们的 d d d 数组的含义发生了变化,在最短路中它的含义是到源点的最短距离,在生成树中它的含义是到生成树的最短距离。你把加入生成树的所有点看成一个整体,把它看成一个大源点,就可以很好理解为什么判断条件是 w < d [ v ] w<d[v] w<d[v] 了。

其实这里还有另一种理解方式:当某个点加入生成树后,它距离生成树的距离就变为了 0 0 0,然后我们再以这个点为中转点去松弛周围的点,所以判断条件就是 d [ u ] + w < d [ v ] ⇒ 0 + w < d [ v ] ⇒ w < d [ v ] d[u]+w<d[v]\Rightarrow 0+w<d[v]\Rightarrow w<d[v] d[u]+w<d[v]0+w<d[v]w<d[v]。这样理解,其实 p r i m prim prim 算法还可以理解为就是一个最短路算法。


回到这个题,这个题 n , m n,m n,m 均是 5 × 1 0 5 5\times 10^5 5×105,所以需要写一个 n log ⁡ n\log nlog 的算法。这意味着我们只能跑一个最短路或者生成树。那怎么在跑出 k k k 个关心点之间的最短路,然后找到生成树呢?

如果我们只看 k k k 个关心点,而忽视掉其他的点和互相的路径,那么它就是要给 k k k 个点跑最小生成树。而在某个生成树边上,两个点之间却是跑了一个最短路。

那么我们套用上面 p r i m prim prim 的第二种方式,在整张图上跑最短路,每当一个关心点加入生成树时,就把它到生成树的距离置为 0 0 0,然后继续向其他点跑最短路不就好了。

code:

#include <iostream>
#include <cstdio>
#include <queue>
#include <set>
#define debug(x) cout<<#x<<":"<<x<<endl 
using namespace std;
typedef long long ll;
const int maxn=5e5+5;
const ll linf=1e18;ll T,n,m,k;
set<ll> nd;
ll head[maxn],ent;
struct edge{ll v,w,nxt;
}e[maxn<<1];
void add(int u,int v,ll w){e[++ent]={v,w,head[u]};head[u]=ent;
}struct Node{ll u,dis;bool operator<(const Node a)const{return dis>a.dis;}
};
ll dis[maxn];
bool vis[maxn];
priority_queue<Node> heap;
ll ans=0;
void dij_prim(ll root){for(int i=1;i<=n;i++)dis[i]=linf,vis[i]=false;dis[root]=0;ans=0;heap.push({root,0});while(!heap.empty()){auto [u,distance]=heap.top();heap.pop();if(distance>dis[u])continue;if(nd.find(u)!=nd.end())if(vis[u])continue;else {//加入生成树 vis[u]=true;ans+=dis[u];dis[u]=0;}for(int i=head[u];i;i=e[i].nxt){auto [v,w,nxt]=e[i];if(dis[u]+w<dis[v]){dis[v]=dis[u]+w;heap.push({v,dis[v]});}}}
}int main(){cin>>T;while(T--){cin>>n>>m>>k;ent=0;for(int i=1;i<=n;i++)head[i]=0;nd.clear();for(int i=1,u,v,w;i<=m;i++){cin>>u>>v>>w;add(u,v,w);add(v,u,w);}for(int i=1,t;i<=k;i++){cin>>t;nd.insert(t);}dij_prim(*nd.begin());cout<<ans<<endl;}return 0;
}

G Jump Sort

思路:

挺有意思的数学题。

想象一下,如果某个数排序前的位置是 a a a,排序后的位置是 b b b,那么它需要移动 d i s = ∣ a − b ∣ dis=|a-b| dis=ab 的距离。那么你选择的 x x x 就必须是 d i s dis dis 的因数。否则 d i s dis dis 无法整除 x x x 的话,就无法通过整数次移动正好得到 d i s dis dis 的距离。

同理,对每个数都有一个 d i s dis dis,我们必须保证 x x x 同时是 n n n d i s dis dis 的因数,也就是 x x x 是且仅是 n n n d i s dis dis 的最大公因数的因数

因为这个题给的是一个排列,所以 a = i , b = a i a=i,b=a_i a=i,b=ai d i s i = a b s ( i − a i ) dis_i=abs(i-a_i) disi=abs(iai)。求它们的最大公因数,再求取公因数的因数个数即为答案。

不过可能有人会质疑这样选取 x x x 的可行性,认为选取了 x x x 只能保证一个数一定能到达正确位置,不能保证每个数都可以到达正确位置。证明:对于间隔正好为 x x x 的一串数(比如 a s , a s + x , a s + 2 x , … a_{s}, a_{s+x},a_{s+2x},\dots as,as+x,as+2x,),我们可以通过冒泡排序的思想把它排为有序。其实我们如果人为去规定每个数的大小,那么我们就可以实现一个任意的排序序列,也就是说通过相邻数交换的这种操作我们可以给一串数任意排列,这样,我们就可以实现所有数都到达正确位置了。

最后提醒一下,规定上 gcd ⁡ ( 0 , a ) = a \gcd(0,a)=a gcd(0,a)=a,所以不需要特判 d i s = 0 dis=0 dis=0 的情况。
特殊情况:当序列已经有序的时候,答案是 n n n

code:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
const int maxn=5e5+5;
typedef pair<int,int> pii;int n,d;int gcd(int a,int b){while(b)b^=a^=b^=a%=b;return a;
}int main(){cin>>n;for(int i=1,t,dis;i<=n;i++){cin>>t;dis=abs(t-i);d=gcd(d,dis);}int cnt=0;for(int i=1;i*i<=d;i++){if(d%i==0){cnt++;if(i*i!=d)cnt++;}}if(d)cout<<cnt;else cout<<n;return 0;
}

I 好想成为人类啊

思路:

这个题其实很简单的,不知道为什么通过数这么少。

首先每组的 n , m ≤ 1 0 3 n,m\le 10^3 n,m103,而且 ∑ n , m ≤ 2 14 ≈ 15000 \sum n,m\le 2^{14}\approx15000 n,m21415000,这意味着我们跑 O ( n 2 ) O(n^2) O(n2) 算法都没问题,可以直接暴力判断字符串是否匹配。假设匹配位置为 l l l,那么 r = l + m − 1 r=l+m-1 r=l+m1,我们只要 l ∼ r l\sim r lr 里选取一个点即可。

然后问题就转化为了区间选点问题,而且这个题每个区间长度还都是固定的,直接贪心就做完了

code:

#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;int T;
int n,m;
string s,t;vector<int> match;int main(){cin>>T;while(T--){cin>>n>>m>>s>>t;match.clear();for(int i=0;i<=n-m;i++)if(s.substr(i,m)==t)match.push_back(i);int ans=0,len=match.size();for(int l=0,r;l<len;l=r+1){r=upper_bound(match.begin(),match.end(),match[l]+m-1)-match.begin()-1;ans++;}cout<<ans<<endl;}return 0;
}

文章转载自:

http://MCdPpPgD.ryqsq.cn
http://DBAYhSmz.ryqsq.cn
http://71MVDaHq.ryqsq.cn
http://hc7V5Au3.ryqsq.cn
http://eIqIMrHn.ryqsq.cn
http://JgvLDWH6.ryqsq.cn
http://f1Jhdfg0.ryqsq.cn
http://fQsdcO7H.ryqsq.cn
http://nGHiyk6o.ryqsq.cn
http://yd3cgNER.ryqsq.cn
http://ax8QA4o5.ryqsq.cn
http://JCFSxaIZ.ryqsq.cn
http://0MTHhS84.ryqsq.cn
http://zBkbgwz9.ryqsq.cn
http://4HqM4F70.ryqsq.cn
http://796Bls0E.ryqsq.cn
http://H9hm0qut.ryqsq.cn
http://1uNP5zgL.ryqsq.cn
http://gfsTIEnQ.ryqsq.cn
http://neITkYBR.ryqsq.cn
http://5IzxSXzx.ryqsq.cn
http://1e7IzepH.ryqsq.cn
http://F06Lo7DQ.ryqsq.cn
http://diWWL8Sb.ryqsq.cn
http://f4mCrqH4.ryqsq.cn
http://BBTKDD3H.ryqsq.cn
http://RgIdpWHx.ryqsq.cn
http://9I0ft2nb.ryqsq.cn
http://73Mv1Pfo.ryqsq.cn
http://UP7fVN1Y.ryqsq.cn
http://www.dtcms.com/wzjs/715304.html

相关文章:

  • 女生做网站编辑好还是咸宁住房和城乡规划建设局网站
  • 建设通网站怎么注销小程序源码在哪个平台购买
  • 微信小程序制作视频教程网络优化工程师有多累
  • 百度怎么创建网站网站怎样自己做推广
  • 陕西网站建设制作上海网站建设公司费用
  • 怎样建设网站是什么网络营销的特点主要有哪些
  • 云南旅行社网站建设微信小程序商城怎样做
  • 做自己的网站要多少钱门头沟新乡网站建设
  • 上海seo网站建设怎么在广告联盟接广告
  • 福田企业的网站建设公司好吗网站的创建历程怎么写
  • 网站搭建设计 是什么江汉建站公司
  • 唐山建设集团下岗职工网站微商城网站建设报价
  • 制作网站网页北京建设管理有限公司官网
  • 基于php的个人网站设计论文工商网企业信息查询系统上海
  • 辽宁建设工程招标网站默认开启评论 wordpress
  • 聊城菜鸟网站建设公司网络技术网站是做什么的
  • 做网站费用记入什么会计科目交换链接营销的经典案例
  • 做养生网站需要什么资质无需代码制作app软件
  • 软件公司网站建设2008vps做网站
  • 简单的网站怎么做集团有限公司成立条件
  • 做家教去哪个网站互联网营销师报名
  • 龙岗建网站公司wordpress 增加小工具
  • 百姓网网站建设网络营销外包平台
  • 做网站需要钱吗wordpress 微信抓取
  • 营销型网站深度网中国多少个省份31个省
  • 迅速编程做网站青岛做网站的大公司有
  • python网站开发框架怎样帮拍卖网站做策划
  • 网站制作设计说明手机支付网站开发
  • 网站开发怎么进行数据库连接石家庄网站快速排名
  • 网站无法处理请求商城网站建设报价方案