题意: 现有 n 条链,第 i 条链的头结点连接第 i-1 条链的第 a[i] 号点,其尾结点连接第 i-1 条链的第 b[i] 号点;先让你找出最大的环的边数。
思路:
- 从前往后扫一遍,求一个答案的最大值就好。
- 如果当前链被下一条链连接的是同一个结点,那么表示环到当前位置必须结束了,且开始下一个环,更新中间答案 tmp == 0。
- 扫描的过程中也要考虑在当前(每一条)链结束会不会答案更大的情况。
- 同样还要注意,如果以当前链为环的起点会不会比前面的起点答案更大。
- 具体细节都注释在代码中。
代码实现:
#include<bits/stdc++.h>
#define endl '\n'
#define null NULL
#define ll long long
#define int long long
#define pii pair<int, int>
#define lowbit(x) (x &(-x))
#define ls(x) x<<1
#define rs(x) (x<<1+1)
#define me(ar) memset(ar, 0, sizeof ar)
#define mem(ar,num) memset(ar, num, sizeof ar)
#define rp(i, n) for(int i = 0, i < n; i ++)
#define rep(i, a, n) for(int i = a; i <= n; i ++)
#define pre(i, n, a) for(int i = n; i >= a; i --)
#define IOS ios::sync_with_stdio(0); cin.tie(0);cout.tie(0);
const int way[4][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};
using namespace std;
const int inf = 0x7fffffff;
const double PI = acos(-1.0);
const double eps = 1e-6;
const ll mod = 1e9 + 7;
const int N = 2e5 + 5;
int t, n;
int c[N], a[N], b[N];
signed main()
{
IOS;
cin >> t;
while(t --){
cin >> n;
for(int i = 1; i <= n; i ++) cin >> c[i];
for(int i = 1; i <= n; i ++) cin >> a[i];
for(int i = 1; i <= n; i ++) cin >> b[i];
int ans = 0, tmp = 0;
for(int i = 1; i <= n; i ++)
if(a[i]>b[i]) swap(a[i], b[i]);
tmp += b[2]-a[2];
for(int i = 2; i <= n; i ++){
tmp += 2;
ans = max(ans, tmp+c[i]-1); // 如果到当前链结束。
if(i==n){
tmp += c[i]-1;
ans = max(ans, tmp); // 如果已经找到最后一条链
break;
}
if(a[i+1]==b[i+1]){ // 如果必须在当前链结束
ans = max(ans, tmp+c[i]-1);
tmp = 0;
}
else{ // 如果不在当前链结束
tmp += a[i+1]-1+c[i]-b[i+1];
tmp = max(tmp, b[i+1]-a[i+1]); // 如果当前链的贡献比前面的贡献都大
}
ans = max(ans, tmp);
// cout << "debug: " << i << " " << ans << endl;
}
cout << ans << endl;
}
return 0;
}