10.7 div2复现赛
P14178 「FAOI-R8」Jueves
可以发现一些性质:
- 当 $s=t$ 时,显然答案为 0
- 否则,最短路一定是连接 $s$ 与 $t$ 的那条边,因为 $(a_u xor a_v)+(a_u or a_v)+(a_u and a_v) > a_u$。
所以代码非常简单:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=5e5+5;
int T,n,s,t;
int a[N];
signed main(){
cin>>T;
while(T--){
cin>>n>>s>>t;
for(int i=1;i<=n;i++) cin>>a[i];
if(s==t) cout<<0<<endl;
else cout<<(a[s]^a[t])+(a[s]|a[t])+(a[s]&a[t])<<endl;
}
return 0;
}P14179 「FAOI-R8」喵了个喵 V
首先无视 $m$ 的取值根据题意模拟求出字典序最小的答案数组,
若此时 $m<0$,无解;$m=0$ 则刚好得出答案;
若 $m>0$,则再次按照性质从大到小尽可能地匀给当前位置,
然后就能得出答案了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+5;
int T;
int n,d,m;
int a[N];
bool b[N];
signed main(){
cin>>T;
while(T--){
int y=1;
cin>>n>>d>>m;
for(int i=1;i<=n;i++) cin>>b[i],a[i]=0;;
for(int i=1;i<=n;i++){
a[i]+=a[i-1];
if(b[i]){
if(a[i]%d==0){
m-=a[i];
continue;
}
int add=d-(a[i]%d);
a[i]+=add,m-=a[i];
if(m<0) y=0;
}
else{
if(a[i]%d!=0){
m-=a[i];
continue;
}
a[i]++,m-=a[i];
if(m<0) y=0;
}
}
if(m>0){
for(int i=n;i>=1;i--){
if(!m) break;
if(b[i]){
if(i==n){
a[i]+=(m-(m%d)),m=m%d;
continue;
}
int cha=(a[i+1]-(a[i+1]%d))-a[i];
if(cha<=m){
a[i]+=cha;
m-=cha;
}
else{
a[i]+=(m-(m%d)),m=m%d;
}
}
else{
if(i==n||m<=a[i+1]-a[i]){
if((a[i]+m)%d==0) a[i]+=m-1,m=1;
else a[i]+=m,m=0;
}
else{
if(a[i+1]%d==0) m-=a[i+1]-a[i]-1,a[i]=a[i+1]-1;
else m-=a[i+1]-a[i],a[i]=a[i+1];
}
}
if(m<0||(a[i]>a[i+1]&&i!=n)) y=0;
}
}
if(y==0||m!=0) cout<<"No\n";
else{
for(int i=1;i<=n;i++) cout<<a[i]<<" ";
cout<<"\n";
}
}
return 0;
}P1651 塔
差值 DP。
设选到了第 $i$ 个木块,左塔减右塔的值为 $j$ 时,左塔最高的高度为 $dp_{i,j}$。
就可以分类讨论 $a_i$ 是不放还是放在左塔还是放在右塔。
注意到 $j$ 的值是会小于零的,所以我们给 $j$ 整体加上 $500000$ 就可以了。
代码:
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+5;
int n,ans;
int a[55],dp[N],dp1[N];
signed main(){
memset(dp,128,sizeof dp);
memset(dp1,128,sizeof dp1);
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
dp1[500000]=0;
for(int i=1;i<=n;i++){
for(int j=0;j<N;j++){
dp[j]=max(dp[j],dp1[j]);
if(j-a[i]>=0) dp[j]=max(dp[j],dp1[j-a[i]]+a[i]);
if(j+a[i]<N) dp[j]=max(dp[j],dp1[j+a[i]]);
if(j==500000) ans=max(ans,dp[j]);
}
for(int j=0;j<=N;j++){
dp1[j]=dp[j];
}
}
if(ans>0) cout<<ans;
else cout<<-1;
return 0;
}

Comments 1 条评论
%%%%%%%%%%%%%%%