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

邢台做移动网站费用外链推广

邢台做移动网站费用,外链推广,华艺网络网站开发,网林时代网站建设文章目录 T1T2法一:倍增求 LCA法二:Dijkstra 求最短路法三:dfs 求深度 T3T4总结 T1 一道非常简单的题,结果我因为一句话没写挂了 80pts…… 题目中没写 a a a 数组要按照 b b b 数组的顺序,所以对于最大方案&#x…

文章目录

  • T1
  • T2
    • 法一:倍增求 LCA
    • 法二:Dijkstra 求最短路
    • 法三:dfs 求深度
  • T3
  • T4
  • 总结

T1

一道非常简单的题,结果我因为一句话没写挂了 80pts……

题目中没写 a a a 数组要按照 b b b 数组的顺序,所以对于最大方案,我们需要从最小的开始,这样后面的才有可能填上。

所以一开始我们要先对 b b b 数组从小到大排序(我就是少写了这一行……),然后我们就可以开始算方案数了,怎么算呢?

很简单,首先对于 a 1 a_1 a1,它前面没有任何数,所以它能取的方案书就是 b 1 b_1 b1,然后思考 a 2 a_2 a2,它前面已经有一个数被选了(因为从小到大排序后后面的数一定包含了前面的数),所以对于 a 2 a_2 a2 来讲它有 b 2 − 1 b_2-1 b21 种选择,然后是 a 3 , a 4 … a_3,a_4\dots a3,a4,一直到 a n a_n an,这时我们很容易发现:对于 a i a_i ai 来讲,它有 b i − i + 1 b_i-i+1 bii+1 种选择,再根据乘法原理可知答案是:

a n s = ∏ i = 1 n b i − i + 1 ans=\prod_{i=1}^nb_i-i+1 ans=i=1nbii+1

然后直接输出答案即可。

(老规矩。)

T2

这道题很简单,这里我提供三种做法。

在此之前,我们首先要确定一件事:如果牛郎与织女之间的距离是一个奇数,那么他们会在桥上,否则会在星球上。接下来就是怎么求距离的问题了。

法一:倍增求 LCA

我们可以通过倍增求 LCA 并记录下距离,代码很简单,时间复杂度: O ( Q log ⁡ 2 ( N ) ) O(Q\log_2(N)) O(Qlog2(N))

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,q,l,depth[100006],st[100006][26];
vector<int>v[100006];
void LCA(int x,int y)
{if(depth[x]<depth[y]){swap(x,y);}for(int i=20;i>=0;i--){if(depth[st[x][i]]>=depth[y]){x=st[x][i];l+=(1<<i);}}//这里为了节省时间,我直接把后面求 LCA 的过程省略了。//因为后面的跳动都是两边同时跳,那么每次加的距离都是偶数,而加偶数并不会改变它的奇偶性。
}
void dfs(int x,int deep,int fa)
{st[x][0]=fa;depth[x]=deep;for(auto i:v[x]){if(i==fa){continue;}dfs(i,deep+1,x);}
}
signed main()
{// freopen("bridge.in","r",stdin);// freopen("bridge.out","w",stdout);cin>>n>>q;for(int x,y,i=1;i<n;i++){cin>>x>>y;v[x].emplace_back(y);v[y].emplace_back(x);}dfs(1,1,0);for(int i=1;i<=20;i++){for(int j=1;j<=n;j++){st[j][i]=st[st[j][i-1]][i-1];}}while(q--){int x,y;l=0;cin>>x>>y;LCA(x,y);if(l&1){cout<<"Y"<<endl;}else{cout<<"N"<<endl;}}return 0;
}

法二:Dijkstra 求最短路

我们可以把它看作一张图,然后直接跑最短路。

(我没有代码,读者自己写吧……)

法三:dfs 求深度

我们可以把两点间距离,看作是两点间的深度之和,然后判断奇偶。

代码(题解的):

#include <bits/stdc++.h>
#include <stdio.h>
using namespace std;
int n, q, a, b;
vector<vector<int>> s(1e5 + 1);
vector<int> d(1e5 + 1, 1e5);
void dfs(int x, int y) {d[x] = y;for (auto p : s[x]) {if (d[p] > y + 1) {dfs(p, y + 1);}}
}
int main() {cin >> n >> q;for (int i = 0; i < n - 1; i++) {cin >> a >> b;s[a].push_back(b);s[b].push_back(a);}dfs(1, 0);for (int i = 0; i < q; i++) {cin >> a >> b;cout << (((d[a] + d[b]) % 2 == 0) ? "N" : "Y") << endl;}
}

三种方法,任你选择。

T3

一道不是很简单的题……

我的基础想法是用 tarjan 缩点然后再做,但是图不连通,那么跑 tarjan 的时间复杂度就到了 O ( n 2 ) O(n^2) O(n2),所以明显不行。

然后我又思考过跑 dfs 来找连通块,结果时间复杂度还是 O ( n 2 ) O(n^2) O(n2)

于是就只有一种方法了:并查集

然后我们就可以标记连通块了。

当然,我们肯定要用个 vector 保存下来每个连通块内的点,接下来又该怎么做呢?

我们要代价最小,说白了就是找离 i i i 最近的点 j j j,然后我就有了一个想法:二分!(从时间复杂度上也看得出来是 O ( T × N log ⁡ 2 ( N ) ) O(T\times N\log_2(N)) O(T×Nlog2(N))

我们可以用 lower_bound 找出第一个大于等于 i i i 的点,那么它的上一个就是最后一个小于 i i i 的点,这两个点就必然是离 i i i 最近的两个点,然后记录下来就行了。

我们要让 1 1 1 能到 n n n 连通,那么我们就只需要稍微改一下上面的过程:在包含的 1 1 1 这个连通块里面二分找第 i i i 个点的 lower_bound

因为二分需要单调性,所以我们可以在这之前对每个连通块里面的点排序一下,但这明显会 T L E \color{blue}{TLE} TLE,又该怎么优化呢?

很简单,我们只需要请出排序的“老大哥”——set。我们把 vector 换成 set 就行了。

然后就水灵灵的 A C \color{green}{AC} AC 了!

代码:

#include<bits/stdc++.h>
#define int long long
#define INF 0x3f3f3f3f3f3f3f3f
using namespace std;
int t,n,m,num,ans=INF,fa[100006],col[100006],b[100006],cost[2][100006];
set<int>s[100006];
int find(int x)
{if(fa[x]==x){return x;}return fa[x]=find(fa[x]);
}
signed main()
{cin>>t;while(t--){ans=INF;//初始化!!!for(int i=1;i<=num;i++){s[i].clear();}num=0;memset(b,0,sizeof(b));memset(col,0,sizeof(col));cin>>n>>m;for(int i=1;i<=n;i++){fa[i]=i;}for(int i=1,x,y;i<=m;i++){cin>>x>>y;int xb=find(x);int yb=find(y);if(xb!=yb){fa[yb]=xb;}}if(find(1)==find(n)){cout<<0<<endl;continue;}for(int i=1;i<=n;i++){if(!b[find(i)]){b[find(i)]=col[find(i)]=++num;s[num].insert(i);}else{col[find(i)]=b[find(i)];s[col[find(i)]].insert(i);}}memset(cost,INF,sizeof(cost));for(int i=1;i<=n;i++){if(find(i)==find(1)){continue;}auto it=s[col[find(1)]].lower_bound(i);auto it1=it;if(it1==s[col[find(1)]].end()){it1--,it--;}else if(it1==s[col[find(1)]].begin());else{it--;}cost[0][col[find(i)]]=min({cost[0][col[find(i)]],((*it)-i)*((*it)-i),((*it1)-i)*((*it1)-i)});}for(int i=1;i<=n;i++){if(find(i)==find(n)){continue;}auto it=s[col[find(n)]].lower_bound(i);auto it1=it;if(it1==s[col[find(n)]].end()){it1--,it--;}else if(it1==s[col[find(n)]].begin());else{it--;}cost[1][col[find(i)]]=min({cost[1][col[find(i)]],((*it)-i)*((*it)-i),((*it1)-i)*((*it1)-i)});}for(int i=1;i<=n;i++){if(find(i)==find(1)){continue;}else if(find(i)==find(n)){ans=min(ans,cost[0][col[find(n)]]);}else{ans=min(ans,cost[0][col[find(i)]]+cost[1][col[find(i)]]);}}cout<<ans<<endl;}return 0;
}

当然,这份代码稍微复杂了点,看看题解代码:

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define N 100010
int n, m, i, j, k;
set<int>s[N];
set<int>::iterator it, jt, kt;
int f[N], p[N], u, v, a, b, ans, t;
int fa(int x) {return f[x]==x ? x : f[x]=fa(f[x]);
}
int pingfang(int x) {return x*x;
}
int len(int x, int y) {int ans=1e18;for(it=s[x].begin(); it!=s[x].end(); ++it) {jt=s[y].lower_bound(*it);if(jt!=s[y].end()) ans=min(ans, pingfang((*jt)-*it));if(jt!=s[y].begin()) ans=min(ans, pingfang((*(--jt))-*it));}return ans;
}
signed main() {scanf("%lld", &t);while(t--) {scanf("%lld%lld", &n, &m);for(i=1; i<=n; ++i) f[i]=i;for(i=1; i<=n; ++i) s[i].clear();for(i=1; i<=m; ++i) scanf("%lld%lld", &u, &v), f[fa(u)]=fa(v);for(i=1; i<=n; ++i) s[fa(i)].insert(i);a=f[1];b=f[n];ans=len(a, b);for(i=1; i<=n; ++i) {if(f[i]==a||f[i]==b||f[i]!=i) continue;ans=min(ans, len(i, a)+len(i, b));}printf("%lld\n", ans);}return 0;
}

真简略……

T4

我的评价:特别简单但是很迷惑人……

这题看上去很复杂,实则一点也不复杂。

对于 50pts,我们可以这么思考:如果两个点之间可以互相运送垃圾,则连上一条边,那么同一个连通分量中,所有的垃圾都可以汇集到一个点上,所以问题等价于询问图中有多少个连通分量。

但是这样做最坏情况下时间复杂度为 O ( n 2 ) O(n^2) O(n2),所以我们肯定要换种方法。

(由于作者实在不是很会描述(懒),于是贴上了一份题解。)

我们对所有点按照 x x x 坐标排序,如果前面的点中 y y y 的最小值小于当前点,我们则对这两个点连边。
同时我们倒序遍历,如果后面点的 y y y 的最大值大于当前点,我们则对这两个点连边。
这样边的数量就降为了 O ( n ) O(n) O(n)

(说实话,我也没太看懂……只是大致有感觉。)

代码:

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,x[100006],y[100006],mny[100006],mxy[100006],a[100006];
bool cmp(int xx,int yy)
{return x[xx]<x[yy]||x[xx]==x[yy]&&y[xx]<y[yy];
}
signed main()
{cin>>n;for(int i=1;i<=n;i++){cin>>x[i]>>y[i];a[i]=i;}sort(a+1,a+n+1,cmp);mny[1]=y[a[1]];for(int i=2;i<=n;i++){mny[i]=min(mny[i-1],y[a[i]]);}mxy[n]=y[a[n]];for(int i=n-1;i>=1;i--){mxy[i]=max(mxy[i+1],y[a[i]]);}int ans=1;for(int i=1;i<n;i++){if(mny[i]>mxy[i+1]){ans++;}}cout<<ans;return 0;
}

总结

  1. T1: 本来应该 A C \color{green}{AC} AC 的,结果挂了 80pts……
  2. T2: 完美 A C \color{green}{AC} AC
  3. T3: 理论上来讲可以拿到 50pts,但因为一些奇奇怪怪的计算机底层问题而 W A \color{red}{WA} WA 了……(还有 T L E \color{blue}{TLE} TLE。)
  4. T4: 根本不会,直接输出了样例,骗到 8pts。

总分:129pts,满分 400pts,反正我不满意。

http://www.dtcms.com/wzjs/504784.html

相关文章:

  • 男女做暖暖免费网站网络营销的优势
  • 电商网站 厦门公司网络推广的作用
  • b北京网站建设seo方案
  • 无忧网站建设费用郑州短视频代运营公司
  • 网站页面模板网络营销课程学什么
  • wordpress 网站建设中网络营销的步骤
  • 做微信的网站长沙岳麓区
  • wordpress 模板 中文提供搜索引擎优化公司
  • 网站进行诊断淘宝seo搜索优化工具
  • 网架公司的名称淄博搜索引擎优化
  • 寮步镇仿做网站数据分析网站
  • 使用joomla的网站怎么出售友情链接
  • 米拓企业网站管理系统如何做网站推广私人
  • 下载网站上的表格 怎么做新浪博客
  • 深圳做网上商城网站链接提交
  • 怎么做网站后台界面建立一个网站的费用
  • 网站建设专业英文免费企业网站建设流程
  • 用element做的网站seo搜索价格
  • 营销型网站建设有哪些特点白城seo
  • 网站建设模板html免费的域名和网站
  • 联通公网ip申请 做网站热搜榜百度
  • 网站链接如何做二维码百度极速版客服电话
  • 给企业做网站的公司西安今日新闻摘抄10条简短
  • 网络课程网站模板市场营销方案范文5篇
  • 电子商务网站建设精英百度推广代理商利润
  • 重庆企业网络推广软件廊坊seo
  • 网站建设销售话术河南网站优化
  • 贵州省建设学校网站win7一键优化工具
  • 如何做好品牌宣传工作网站seo方案模板
  • 网站 网页数量搜索关键词的网站