1400——1195C;upc组队赛

今天是2021.10.3。
早上把昨天upc上的题补了,中午一场组队赛,晚上刷了道1400。


C: Distribution Center (思维)

题意:

一共 n 条平行传送带,每条传送带下面可能有一个机械臂,能够将下一条传送带上的物品调上来,或者把当前传送带上的物品调下去。
问,每条传送带最多能够得到多少条传送带上的物品?

思考:

因为传送带从左往右移动,所有左边的机械臂拥有优先权。
所以从左往右遍历所有机械臂。
当前机械臂可以把当前传送带往上能够拿到的物品调到下一传送带;也可以把下一传送带往下能够拿到的物品调到当前传送带。

所以每条传送带能够算出能得到物品的最上端和最下端,也就能计算出能够得到的物品种类了。

实现:

将所有机械臂位置从前往后排序,遍历所有机械臂:
下一传送带能得到的最上面位置与当前带最上面位置取min //由当前机械臂将当前行传送带的最上面位置调下去
当前传送带能得到的最下面位置与下一传送带最下面位置取max //由当前机械臂将下一行传送带的最下面位置调上来

Code:

const int N = 200010;
int T, n, m;
PII a[N];
int up[N],down[N];

int main(){
	cin>>n>>m;
	
	for(int i=1;i<=n;i++) up[i]=i,down[i]=i;
	
	for(int i=1;i<=m;i++) cin>>a[i].first>>a[i].second;
	
	sort(a+1,a+m+1);
	
	for(int i=1;i<=m;i++)
	{
		int y=a[i].second;
		up[y+1]=min(up[y],up[y+1]);
		down[y]=max(down[y],down[y+1]);
	}
	
	for(int i=1;i<=n;i++) cout<<down[i]-up[i]+1<<" ";
	
	return 0;
}

Forest for the Trees (数论)

题意:

给出两个点(0,0)和(x,y)。给出一个矩形的左下角和右上角(a1,a2),(b1,b2),其中所有的整数点都被消除。如果(0,0)和(x,y)连线上有整数点,则不能从(0,0)点看到(x,y)。
如果能,输出Yes;否则,输出距离最近的挡住视线的整数点。

思路:

遍历连线上的所有整数点:
如果这个点在矩形中,没问题,继续遍历。
否则,这个点挡住视线了,输出。

但是,所给坐标的范围为1e12,无法直接遍历所有x,判断y是否为整数。

如何遍历在直线 y = kx 上的整数点呢?

斜率 k = y 0 ÷ x 0 y_0 \div x_0 y0÷x0
为了使得 y 为整数,x 只能为 x 0 x_0 x0 的倍数。( x 0 , y 0 x_0,y_0 x0,y0 互质)
所以直接遍历 x 0 x_0 x0 的倍数就可以了。

Code:

const int N = 200010, mod = 1e9+7;
int T, n, m;
int a[N],b[N];

signed main(){
	int x,y,a1,a2,b1,b2;
	cin>>x>>y;
	
	cin>>a1>>a2>>b1>>b2;
	
	int g=__gcd(x,y);
	if(g==1){
		cout<<"Yes";return 0;
	}
	
	int t=x/g,tt=y/g;
	
	for(int i=1;i*t<x;i++)
	{
		int tx=i*t,ty=i*tt;
		
		if(tx>=a1&&tx<=b1&&ty>=a2&&ty<=b2) continue;
		cout<<"No\n"<<tx<<" "<<ty;
		return 0; 
	}
	cout<<"Yes";
	return 0;
}

其实,数据水了:如果 x 0 x_0 x0为1,矩形的面积足够大,那么倍数就要枚举1e12次了了。
所以需要跳过在矩形中的x坐标计算。


1195.C Basketball Exercise (dp)

题意:

从A,B两个序列中,每个位置可以选择Ai或Bi中的一个,也可以不选。
要满足:选择的序列中,相邻的两个数不能在同一个序列。
问,如何选择,使得选择序列的所有元素之和最大?

思考:

dp

记录当前位置是选择第一个,第二个,还是不选。
如果选择第一个,f[i][1]就从上一个位置选择第二个或者不选的状态转移过来;
如果选择第二个,f[i][2]就从上一个位置选择第一个或者不选的状态转移过来;
如果不选,f[i][0]就可以为上一位置选或者不选的最大值。

取这三种状态的最大值。

Code:

const int N = 200010, mod = 1e9+7;
int T, n, m, a[N], b[N];
ll f[N][3];

int main(){
	Ios;
	cin>>n;
	for(int i=1;i<=n;i++) cin>>a[i];
	for(int i=1;i<=n;i++) cin>>b[i];
	
	ll ans=0;
	for(int i=1;i<=n;i++)
	{
		f[i][0]=max(f[i-1][0],max(f[i-1][1],f[i-1][2]));
		f[i][1]=max(f[i-1][0],f[i-1][2])+a[i];
		f[i][2]=max(f[i-1][0],f[i-1][1])+b[i];
		
		ans=max(ans,max(f[i][0],max(f[i][1],f[i][2])));
	}
	cout<<ans;
	
	return 0;
}

和上次见到的一样,这个线性dp也是开的两维。


还有一题还没想出来,思路错了,wa了两次了。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值