今天是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了两次了。。