记录---cf1983C. Have Your Cake and Eat It Too

简单记录一下这道算是自己写出来的第一道1400分题目(暴力+前缀和)

目录

一、题目

二、思路和代码


一、题目

输入

10

5

5 1 1 1 1

1 1 5 1 1

1 1 1 1 5

6

1 2 3 4 5 6

5 6 1 2 3 4

3 4 5 6 1 2

4

4 4 4 4

4 4 4 4

4 4 4 4

5

5 10 5 2 10

9 6 9 7 1

10 7 10 2 3

3

4 5 2

6 1 4

1 8 2

3

10 4 10

8 7 9

10 4 10

7

57113 65383 19795 53580 74452 3879 23255

12917 16782 89147 93107 27365 15044 43095

33518 63581 33565 34112 46774 44151 41756

6

6 3 1 8 7 1

10 2 6 2 2 4

10 9 2 1 2 2

5

5 5 4 5 5

1 6 3 8 6

2 4 1 9 8

10

1 1 1 1 1001 1 1 1001 1 1

1 1 1 1 1 1 2001 1 1 1

1 1 1 1 1 1001 1 1 1 1001

输出

1 1 2 3 4 5 
5 6 1 2 3 4 
-1
-1
1 1 3 3 2 2 
-1
1 2 3 4 5 7 
3 6 1 1 2 2 
1 2 3 4 5 5 
1 5 6 7 8 10 

二、思路和代码

        一开始我的想法是找到两个点,使数组长度分成3段,每一段进行判断,满足条件就是答案。我本来想贪心,找到每个下标里3个人最大价值的那个数组开始递增,但是这样要处理的条件就太多了,最后放弃。

        想了1个多小时,最后想从暴力角度找思路,惊奇的发现暴力枚举一共也才6种情况,即遍历3个人在第一段的情况,再遍历另外两个人在第二段的情况,最后判断。当6种情况都不满足时,则没有合法答案,输出-1。

        因为求的是每一段区间的总和,所以使用前缀和优化一下。

代码

#include<iostream>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#include<vector> 
#define int long long
 
using namespace std;

const int N = 2e5+10,INF=0x3f3f3f3f;

typedef pair<int,int> PII;

int T;
int n;
int sum[3][N];
int a[N];
int b[N];
int c[N];
int l[3],r[3];

void solve(){
	cin>>n;
	int tot=0;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		tot+=a[i];
		sum[0][i]=sum[0][i-1]+a[i];
	}
	for(int i=1;i<=n;i++) cin>>b[i],sum[1][i]=sum[1][i-1]+b[i];
	for(int i=1;i<=n;i++) cin>>c[i],sum[2][i]=sum[2][i-1]+c[i];
	
	int t = (tot+2)/3;
	
	for(int i=0;i<3;i++) {//遍历3种开始的情况
		int m=0;
	 	for(int j=1;j<=n;j++){//找到一种情况使某个人满足条件,第一个人一定能找到一种状态满足条件 
		 	if(sum[i][j]-sum[i][0]>=t){
			 	l[i]=1,r[i]=j;
			 	m=j+1;
			 	int k=1;
	 			while((i+k)%3!=i){//剩余两种情况 
	 				int x=(i+k)%3;
	 				l[x]=INF,r[x]=INF; 
	 				for(int d=m;d<=n;d++){
	 					if(sum[x][d]-sum[x][m-1]>=t){
	 						l[x]=m,r[x]=d;
	 						//判断第三个人是否满足
							int y = (3-i-x);//第三个人
							if(sum[y][n]-sum[y][d]>=t){
								l[y]=d+1,r[y]=n;
								for(int i=0;i<3;i++) cout<<l[i]<<" "<<r[i]<<" ";
								puts("");
								return;
							}else break;
	 					}
	 				}
	 				k++;//下一种情况 
	 			}
	 			break;//进行下一种情况 
			}
		}
	}
	cout<<-1<<endl;//没有满足条件的情况 
}
	

signed main(){
	cin>>T;
	while(T--){
		solve();
	}
	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值