Educational Codeforces Round 103 C - Longest Simple Cycle (思維 + 貪心)
技術標籤:思維貪心codeforces 題解c++演算法貪心思維codeforces
Longest Simple Cycle
題意
有
n
n
n 條鏈,第
i
i
i 條鏈上有
c
[
i
]
c[i]
c[i] 個點,
a
[
i
]
a[i]
a[i] 為第
i
i
i 條鏈的頂點與第
i
−
1
i-1
i−1 條鏈的連線點,
b
[
i
]
b[i]
b[i] 為第i條鏈的最後一個點與第
i
−
1
i-1
i−1 條鏈的連線點。
找這樣的一個環,環上的每個點都只被訪問一次,問該環的最大長度為多少。
思路
反向遍歷 c [ i ] c[i] c[i]
設
r
e
s
1
res1
r
e
s
1
res1
res1 表示 每條鏈
a
[
i
]
a[i]
a[i] 和
b
[
i
]
b[i]
b[i] 之間的點的個數 定義為 向內
r
e
s
2
res2
res2 表示 每條鏈
a
[
i
]
a[i]
a[i] 和
b
[
i
]
b[i]
b[i] 到兩個端點的點的個數 定義為 向外
當 a [ i ] ≠ b [ i ] a[i] \neq b[i] a[i]=b[i] 時 :
顯然可知 r e s 1 res1 res1 需要用 r e s 2 res2 res2 來更新 即只有右邊那條鏈選擇向兩個端點 這條鏈才能選擇向內
res1 = res2 + abs(a[i] - b[i]) + 1;
當 i = 2 i = 2 i=2 時 a [ i ] a[i] a[i] 和 b [ i ] b[i] b[i] 表示第2條鏈連在第一條鏈的位置 顯然不能取向外的 因為這樣形成不了環 只能取向內的情況
所以有
if (i != 2)
res2 += c[i - 1] - abs(a[i] - b[i]) - 1 + 2;
else res2 = res1;
當
a
[
i
]
=
b
[
i
]
a[i] = b[i]
a[i]=b[i] 時形成了環 為什麼
r
e
s
2
+
=
1
res2 += 1
所以有
else {
res2 += 1;
maxn = max(maxn, res2);
if (i != 2)res2 = c[i - 1];
}
需要注意的是:
if (res2 < c[i - 1] && i != 2)
res2 = c[i - 1];
可以把還未形成的環看成兩部分 一部分是 r e s 2 res2 res2 表示的上一條鏈取向外操作下的 “環” (此時還未形成環) 一部分(左半邊)還未形成 右邊的環對左邊未找到的環的大小無影響 當 r e s 2 < c [ i − 1 ] res2 < c[i - 1] res2<c[i−1] 時顯然把 第 i − 1 i - 1 i−1 條鏈全部當作環的右半部分更優
程式碼
#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define mod 1000000007
using namespace std;
typedef long long LL;
typedef pair<int, int>PII;
inline LL gcd(LL a, LL b) { return b ? gcd(b, a % b) : a; }
const int N = 100010;
LL a[N], b[N], c[N];
void solve() {
int n; cin >> n;
for (int i = 1; i <= n; ++i)scanf("%lld", &c[i]);
for (int i = 1; i <= n; ++i)scanf("%lld", &a[i]);
for (int i = 1; i <= n; ++i)scanf("%lld", &b[i]);
LL res1 = 0; //向內
LL res2 = 0; //向外
LL maxn = -INF;
res1 = c[n], res2 = c[n];
for (int i = n; i >= 2; --i) {
if (a[i] != b[i]) {
res1 = res2 + abs(a[i] - b[i]) + 1;
if (i != 2)
res2 += c[i - 1] - abs(a[i] - b[i]) - 1 + 2;
else res2 = res1;
maxn = max(maxn, max(res1, res2));
if (res2 < c[i - 1] && i != 2)
res2 = c[i - 1];
}
else {
res2 += 1;
maxn = max(maxn, res2);
if (i != 2)res2 = c[i - 1];
}
}
cout << maxn << endl;
}
int main() {
int t; cin >> t;
while (t--)
solve();
return 0;
}