暑假集训记录

最近感觉状态好多了...做cf的构造题,几乎都会(自信)今天刷了6道构造,就一题没出来..

其他的都出来了并且都是一发ac..我太强了...

好像2个1400,1个1500,3个1600

就一个1600没出来.那题确实有点离谱了..

真的一点思路没有

最近还打牛客多校..我感觉那天我们的状态太差了...我写题的时候要困死了.写的特别不清晰

幸好最好都出来了

最近也没学啥算法..感觉不想学,还是刷codeforces有趣啊..但是还得硬着头皮学啊!!

牛客多校第5场..有一个二分图的最大匹配问题的..

比赛时候看题意都看烦了..并且二分图也一点不会..所以也没做,我们2小时40分钟就下班了...

赛后发现过了快1000了,但是应该好多都是错误的..

这题需要用好多结论的..不补了..麻烦....

登录—专业IT笔试面试备考平台_牛客网

这题是背包dp+区间dp,然后我们也不会....

赛后发现有人用记忆化写出来了.但是有一个点我一直没搞懂

我们用mem[i][j][has]表示当前在第i个奶酪前(还没做任何处理,没挖掉也没拿走)第j个背包现在背包已经有has重量的最大重量

一共有3种情况:

1.如果当前奶酪可拿   :     

if(z[v]-has>=a[u]){
		res=b[u]+dfs(u+1,v,has+a[u]);
	}

2.当前奶酪挖掉,到下一个奶酪并且不换背包

res=max(res,dfs(u+1,v,has));

3.在当前奶酪前换背包,更新当前的背包用了多少

res=max(res,dfs(u,v+1,0));

还有一个非常关键的点!!

我们发现每次背包都是递增的,如果m>=n考虑后n次即可(因为如果前面拿不了,后面可能能拿,后面拿不了前面一定拿不了),否则需要全部考虑

我困惑的点就是这个dp的第二维太离谱了..

如果m为20000,n为200的话,不就超了吗??

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef  long  long ll ;
typedef  unsigned long  long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
int n,m;
int a[100005],b[100005],z[100005]; 
int dp[399][503][205];
int dfs(int u,int v,int has){
    
	if(u>n||v>m){
		
		return 0;
	}
	if(dp[u][v][has])return dp[u][v][has];
	int res=0;
	if(z[v]-has>=a[u]){
		res=b[u]+dfs(u+1,v,has+a[u]);
	}
	res=max(res,dfs(u,v+1,0));
	res=max(res,dfs(u+1,v,has));
	dp[u][v][has]=res;
	return dp[u][v][has];
	 
}
int main(){ 

	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d%d",&a[i],&b[i]);
	}
	
	for(int i=1;i<=m;i++){
		scanf("%d",&z[i]);
	}
		
	cout<<dfs(1,max(1,m-n+1),0)<<endl;
	
	
	return 0;
}


Problem - C2 - Codeforces

这题有点意思.

次数要小于31,我次数优化到了34.

先说我想..感觉是误打误撞的..也没花多少时间,40分钟左右吧

我们统计最小值和最大值以及他们的位置

如果manx<=0的话,说明全为负数...

然后我就0...同时更新最小值

if(maxn<=0){
			for(int i=n;i>=2;i--){
				while(a[i]<a[i-1]){
					a[i-1]=a[i-1]+minn;
					++cnt;
					ans[cnt].x=i-1;
					ans[cnt].y=pos2; 
				}	
				if(a[i-1]<minn){
					pos2=i-1;
					minn=a[i-1];
				}
			}

后来我发现我写的太离谱了.

如果全为正数或者全为负数的话.直接相邻项相加即可(正负顺序不同)

如果maxn>0的话也是一样的..但是只判读这一种会超过50次

for(int i=2;i<=n;i++){
				while(a[i]<a[i-1]){
					a[i]=a[i]+maxn;
					++cnt;
					ans[cnt].x=i;
					ans[cnt].y=pos1; 
					
				}
				if(a[i]>maxn){
					pos1=i;
					maxn=a[i];
				}
			}

如果maxn>0且minn<0的话,我们取maxn和minn最小操作数即可

困难模式正解:

如果全部为正或者全为负,操作次数不超过19次

如果既有整数既有负数的话:我们可以数组全部变为正或者全部为负在排序

排序需要花19次,所以我们还有12次

我们可以构造一个大数,abs(x)>=32至多需要花费5次机会

设x1为造一个正的大数的次数,y1吧数列全部变为正数的次数

设x2为造一个负的大数的次数,y2把数列全部变为负数的次数

x1和x2之间一定有一个为0

因为绝对值最大的一定非正即负.

x1+x2<5

有y1+y2<=n<=20

所以x1+x2+y1+y2<=25

故min(x1+y1,x2+y2)<=12

我一直在考虑min(x1+y1,x2+y2)是否一定小于25/2向下取整

然后就举了几个例子..确实是对的

然后写了200行代码恶心

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef  long  long ll ;
typedef  unsigned long  long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
int t; 
int a[25];
struct Node{
	int x,y;
}ans[105];
int b[25];
int main(){
	scanf("%d",&t);
	while(t--){
		
		int x1,y1;
		x1=0;//正数 
		y1=0;//负数 
		int n;
		scanf("%d",&n);
		int minn=inf;
		int maxn=-inf;
		int pos1;
		int pos2;
		for(int i=1;i<=n;i++){
			scanf("%d",&a[i]);
			if(a[i]>0){
				x1++;
			}
			if(a[i]<0){
				y1++;
			}
			
			b[i]=a[i];
			
			if(a[i]>maxn){
				maxn=a[i];
				pos1=i;
			
			}
			
			if(a[i]<minn){
				minn=a[i];
				pos2=i;
			}		
						
		}
		
		int cnt=0;
		
		if(maxn<=0){
			for(int i=n-1;i>=1;i--){
				cnt++;
				ans[cnt].x=i;
				ans[cnt].y=i+1;
			}
				printf("%d\n",cnt);
				
			for(int i=1;i<=cnt;i++){
				
				printf("%d %d\n",ans[i].x,ans[i].y);
				
			}
			
			continue;
				
		}
		
		
		if(minn>=0){
			
			for(int i=2;i<=n;i++){
				cnt++;
				ans[cnt].x=i;
				ans[cnt].y=i-1;
			}
				printf("%d\n",cnt);
				
			for(int i=1;i<=cnt;i++){
				printf("%d %d\n",ans[i].x,ans[i].y);
			}
			continue;
			
		}
		
		if(abs(maxn)>=abs(minn)){
			
			if(y1+n-1<=31){
				for(int i=1;i<=n;i++){
					if(a[i]<0){
						cnt++;
						ans[cnt].x=i;
						ans[cnt].y=pos1;
					}
				}
				for(int i=2;i<=n;i++){
					cnt++;
					ans[cnt].x=i;
					ans[cnt].y=i-1;
				}		
			}else{
					
				for(int i=1;i<=5;i++){
					cnt++;
					ans[cnt].x=pos2;
					ans[cnt].y=pos2;
					
				}
				for(int i=1;i<=n;i++){
					if(a[i]>0){
						cnt++;
						ans[cnt].x=i;
						ans[cnt].y=pos2;
					}
				}
				for(int i=n-1;i>=1;i--){
					cnt++;
					ans[cnt].x=i;
					ans[cnt].y=i+1;
				}
					
			}
			
			printf("%d\n",cnt);
			for(int i=1;i<=cnt;i++){
				printf("%d %d\n",ans[i].x,ans[i].y);
			}
			
		}else{
			
			if(x1+n-1<=31){
				for(int i=1;i<=n;i++){
					if(a[i]>0){
						cnt++;
						ans[cnt].x=i;
						ans[cnt].y=pos2;
					}
				}
				for(int i=n-1;i>=1;i--){
					cnt++;
					ans[cnt].x=i;
					ans[cnt].y=i+1;
				}	
				
			}else{
				
				for(int i=1;i<=5;i++){
					cnt++;
					ans[cnt].x=pos1;
					ans[cnt].y=pos1;
				}
				for(int i=1;i<=n;i++){
					if(a[i]<0){
						cnt++;
						ans[cnt].x=i;
						ans[cnt].y=pos1;
					}
				}
				for(int i=2;i<=n;i++){
					cnt++;
					ans[cnt].x=i;
					ans[cnt].y=i-1;
				}
									
			}			
			printf("%d\n",cnt);
			for(int i=1;i<=cnt;i++){
				printf("%d %d\n",ans[i].x,ans[i].y);
			}
		}
							
	}	
			
	return 0;
	
}

 

Problem - 1334C - Codeforces

今天唯一被难住的一道题

感觉挺难想的也挺有意思的

最后一直爆炸的怪兽对其他怪兽没有影响

之前爆炸的怪兽除了第一只之外将其打倒需要的子弹数为max(0,a[i+1]-b[i]);当前在i+1

我们只需要维护a[i+1]-max(0,a[i+1]-b[i])的最小值即可

然后最后在加上花费即可

好难想的!!!

#include<cstdio>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<queue>
#include<stack>
#include<deque>
#include<vector>
#include<map>
#include<set>
#include <utility>
#include <list>
using namespace std;
typedef  long  long ll ;
typedef  unsigned long  long ull ;
#define pii pair<int,int>
const int inf = 0x3f3f3f3f;//106110956
inline int read(){
    int x = 0, f = 1;
    char ch = getchar();
    while(ch < '0' || ch > '9'){
        if (ch == '-')
            f = -1;
        ch = getchar();
    }
    while(ch >= '0' && ch <= '9'){
        x = (x<<1) + (x<<3) + (ch^48);
        ch = getchar();
    }
    return x * f;
}
void print(__int128 num) {
	if(num) {
		print(num/10);
		putchar(num%10+'0');
	}
}
int t;
ll a[300005],b[300005];
int main(){
	scanf("%d",&t);
	
	while(t--){
		int n;
		scanf("%d",&n); 
		for(int i=1;i<=n;i++){
			scanf("%lld%lld",&a[i],&b[i]);
		}
		ll ans=0;
		ll minn=1e18; 
		ll cnt=0;
		for(int i=1;i<=n;i++){
			int j;
			if(i==n)j=1;
			else j=i+1;
			
			ans=ans+max(0ll,a[j]-b[i]);
			if(a[j]-max(0ll,a[j]-b[i])<=minn){
				minn=a[j]-max(0ll,a[j]-b[i]);
				if(max(0ll,a[j]-b[i])==0){
					cnt=a[j];
				}else{
					cnt=b[i];
				}
			}
		}
		ans=ans+cnt;
		printf("%lld\n",ans); 
		
	} 


	return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值