C. Longest Simple Cycle

C. Longest Simple Cycle

Title:

There are n chains, there are c[i] points on the i-th chain, a[i] is the connection point between the apex of the i-th chain and the i-1th chain, and b[i] is the i-th chain The connection point between the last point and the i-1th chain. Connecting chains by the above method will produce many loops. Ask the maximum length of these loops.
See sample

4
3 4 3 3
-1 1 2 2
-1 2 2 3

There are 4 points in the second column. The top point in the second column is connected to point 1 in the first column (numbered from top to bottom), and the bottom point in the second column is connected to point 2 in the first column
. :
Insert picture description here

answer:

We enumerate the left boundary of the ring from right to left.
Assuming that the current position is at i, the points contained in the current ring are sum (sum contains the upper and lower end points of the ring from the right boundary to the position of i-1, and the loop is not closed yet)
x And y respectively record the minimum and maximum values ​​of a[i+1] and b[i+1] (that is, the upper and lower bounds of the i-th column) to
start the classification discussion:
if x == y, the loop is over (closed loop) ), the enumeration must be continued with i as the new right boundary.
If sum + x + c[i]-y +1 <c[i] means that the ring formed by the new right boundary with i must be larger than the original ring (If the left boundary is to the left of i). Therefore, we discard the original ring and continue to enumerate the answer to the left with i as the right boundary.
If sum + x + c[i]-y +1 >= c[i], it means that the current ring ratio is composed of i as the right end point The new ring is larger, so keep the original ring and continue to enumerate to the left.
Record the length of the longest closed loop during enumeration

Code:

#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;
}

Guess you like

Origin blog.csdn.net/qq_35975367/article/details/115017343