Educational Codeforces Round 103 (Rated for Div. 2)C. Longest Simple Cycle(贪心)

题目描述

You have n chains, the i-th chain consists of ci vertices. Vertices in each chain are numbered independently from 1 to ci along the chain. In other words, the i-th chain is the undirected graph with ci vertices and (ci−1) edges connecting the j-th and the (j+1)-th vertices for each 1≤j<ci.
Now you decided to unite chains in one graph in the following way:
1.the first chain is skipped;
2.the 1-st vertex of the i-th chain is connected by an edge with the ai-th vertex of the (i−1)-th chain;
3.the last (ci-th) vertex of the i-th chain is connected by an edge with the bi-th vertex of the (i−1)-th chain.
在这里插入图片描述
Picture of the first test case. Dotted lines are the edges added during uniting process
Calculate the length of the longest simple cycle in the resulting graph.
A simple cycle is a chain where the first and last vertices are connected as well. If you travel along the simple cycle, each vertex of this cycle will be visited exactly once.

Input

The first line contains a single integer t (1≤t≤1000) — the number of test cases.
The first line of each test case contains the single integer n (2≤n≤105) — the number of chains you have.
The second line of each test case contains n integers c1,c2,…,cn (2≤ci≤109) — the number of vertices in the corresponding chains.
The third line of each test case contains n integers a1,a2,…,an (a1=−1; 1≤ai≤ci−1).
The fourth line of each test case contains n integers b1,b2,…,bn (b1=−1; 1≤bi≤ci−1).
Both a1 and b1 are equal to −1, they aren’t used in graph building and given just for index consistency. It’s guaranteed that the sum of n over all test cases doesn’t exceed 105.

Output

For each test case, print the length of the longest simple cycle.

Example

input
3
4
3 4 3 3
-1 1 2 2
-1 2 2 3
2
5 6
-1 5
-1 1
3
3 5 2
-1 1 1
-1 3 5
output
7
11
8

Note

In the first test case, the longest simple cycle is shown below:
We can’t increase it with the first chain, since in such case it won’t be simple — the vertex 2 on the second chain will break simplicity.

题目大意

有n条链,第i条链上有c[i]个点,a[i]为第i条链的顶点与第i-1条链的连接点,b[i]为第i条链的最后一个点与第i-1条链的连接点。通过上面的方法连接链会产生很多的环,问这些环的最大长度。

题目分析

O(n2)的做法是不难想的:

for(int i=n;i>1;i--)				//枚举环的右边界
	for(int j=i-1;j>1;j--)			//枚举环的左边界
	{
    
    
		//算出由i链到j链组成环的长度。
		//每次记录最大值
	}

我们主要来想想如果将这个O(n2)的方法优化为O(n)。我们可以用贪心的方法来解决:枚举时只保留最大的环

我们可以从右往左枚举环的左边界,假设当前位置为i,当前环包含的点为sum(这个sum此时记录了当前环从右边界到i-1位置的上下两个端点上 [此环还没有闭合] ),x为a[i-1]和b[i-1]的最小值(即最靠近 i 链1位置的值),y为a[i-1]和b[i-1]的最大值(即最靠近 i 链c[i]位置的值)

这时我们需要进行分类讨论了

  1. 如果 s u m + x + c [ i ] − y + 1 < c [ i ] sum+x+c[i]-y+1<c[i] sum+x+c[i]y+1<c[i],说明以i为新的右边界组成的环一定会大于原有的环(如果左边界在i的左边)。因此我们就舍弃原有的环,以i为右边界继续向左枚举答案。
  2. 如果 s u m + x + c [ i ] − y + 1 > = c [ i ] sum+x+c[i]-y+1>=c[i] sum+x+c[i]y+1>=c[i],说明当前环比以i为右端点组成的新环更大,因此保留原有环,继续向左枚举。
  3. 注意:当x==y时,原有的环就到了尽头(无法再继续往左走了),此时就必须以i为新的右边界继续进行枚举。

在上述的枚举过程中要计算一下以当前位置i为左边界时,组成的环(闭合环)的长度,并记录下最大值。该最大值即为最后的答案。

代码如下
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <bitset>
#include <algorithm>
#define LL long long
#define PII pair<int,int>
#define x first
#define y second
using namespace std;
const int N=1e5+5;
int a[N],b[N],c[N];
int main()
{
    
    
    int t;
	scanf("%d",&t);
	while(t--)
	{
    
    
		int n;
		scanf("%d",&n);
		for(int i=1;i<=n;i++) scanf("%d",&c[i]);
		for(int i=1;i<=n;i++) scanf("%d",&a[i]);
		for(int i=1;i<=n;i++) scanf("%d",&b[i]);
		LL ans=0,sum=0;					//sum表示当前环包含的点数,ans记录环的最大值
		int x=1,y=c[n];					//与上述作用相同
		for(int i=n;i>1;i--)			//从右往左进行枚举
		{
    
    
			if(x==y||sum+x+c[i]-y+1<c[i]) sum=c[i];	//符合条件1,3,以i为新的右边界来组成环,新环的初始长度为c[i]
			else sum+=x+c[i]-y+1;		//符合条件2,继续使用原有环,并更新sum的长度,将i链加入sum
			
			x=min(a[i],b[i]),y=max(a[i],b[i]);		//记录新的x,y值
			ans=max(ans,sum+y-x+1);					//记录最大值
		}
		printf("%lld\n",ans); 			//注意,答案有可能爆int
	}
    return 0;
}

猜你喜欢

转载自blog.csdn.net/li_wen_zhuo/article/details/113415200