0
点赞
收藏
分享

微信扫一扫

2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】


​​题目传送门​​

题目描述

牛牛有一颗大小为n的神奇 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_算法 数组,数组上的每一个节点都有两种状态,一种为 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_算法_02 状态,另一种为 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_算法_03 状态。数组上任意一对处于 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_算法_02 状态的无序点对(即 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_分治算法_052020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_分治算法_06 被认为是同一对)会产生2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_分治算法_072020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_算法_02 能量,2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_分治算法_07为数组上u到v的距离。

我们定义整个数组的 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_分治算法_10 能量为所有处于 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_算法_02 状态的节点产生的 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_算法_02

一开始数组上每个节点的状态将由一个长度大小为 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_分治算法_132020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_数组_14 给出,2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_数组_152020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_ios_16

牛牛想要知道整个数组的 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_分治算法_10 能量,为了避免这个数字过于庞大,你只用输出答案对2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_ios_18取余后的结果即可。

输入描述:

第一行输入一个正整数 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_ios_19

接下里一行输入一个长度大小为n的01串表示数组的初始状态,'1’表示Link状态,'0’表示Cut状态。

输出描述:

仅一行,表示整个数组的Link能量对 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_ios_18

输入

3
101
5
00110
6
000010

输出

2
1
0

题解12020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_分治算法_21

  • 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_分治_22
  • 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_分治算法_23
  • 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_分治算法_24

题解22020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_分治算法_25

  • 分治算法计算贡献,对于每一个区间2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_算法_26,它的中点为 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_数组_27
  1. 左侧区间产生的贡献。
  2. 右侧区间产生的贡献。
  3. 过中点2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_算法_28
  • 那么对于1,2,我们可以使用递归求解,由于区间越分越小,所以最终复杂度总和为2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_分治_29
  • 考虑3,只需要暴力for左侧区间,统计左侧区间"1"的数目,以及它们到中点的和。
    时空复杂度为 2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_分治_29
  • 这个方法虽然不够优秀,但是它可以扩展到线段树上面维护动态问题(也就是解决第二问),线段树其实就是保留了每次分治的结果。
  • 如果学分治的话建议写一写。

AC-Code2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_算法_31

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define
const int maxn = 1e5 + 7;
const int mod = 1e9 + 7;

int main() {
ios;
int n; string s;
cin >> n >> s;
ll ans = 0;
ll num = 0;
int cnt = 0;
for (int i = 0; i < s.size(); ++i) {
num = (num + cnt) % mod; // 如果前面有cnt个1,那么每个1的位置往当前位置的距离都需要+1
if (s[i] == '1') {
if (cnt)
ans = (ans + num) % mod;
++cnt;
}
}
cout << ans << endl;
}

AC-Code2020牛客寒假算法基础集训营3——F.牛牛的Link Power I【计算】【分治】_算法_32

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
const int mod = 1e9 + 7;
char s[MAXN];
int n;
long long ans;
void div_algorithm(int l, int r) {
if (l == r) return;
int mid = (l + r) >> 1;
long long leftsum = 0;
long long leftcnt = 0;
for (int i = mid; i >= l; --i) {
if (s[i] == '1') {
leftsum = (leftsum + mid - i) % mod;
++leftcnt;
}
}
for (int i = mid + 1; i <= r; ++i) {
if (s[i] == '1') {
ans = (ans + leftsum + (i - mid) * leftcnt % mod) % mod;
}
}
div_algorithm(l, mid); // 计算左侧贡献
div_algorithm(mid + 1, r); // 计算右侧贡献
}
int main()
{
scanf("%d", &n);
scanf("%s", s + 1);
div_algorithm(1, n);
printf("%lld\n", ans);
return 0;
}


举报

相关推荐

0 条评论