洛谷刷题7.28
P3745 [六省联考 2017] 期末考试 - 洛谷
前缀和+二分,介于这个题的b比较小,我们可以每次都枚举每门课至少在i天出成绩,取最小值。
cl函数是把课程出分日期都调整到i之前的代价。student函数是学生的不愉快度。
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define jiasu ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
ull a,b,c,n,m,l=100005,r=0,t[100005],s[100005],sum1[100005],sum2[100005];
ull cl(ull x){ull now=upper_bound(s+1,s+1+m,x)-s;ull small=x*(now-1)-sum2[now-1],big=sum2[m]-sum2[now-1]-(m-now+1)*x;if(b<=a) return b*big;else{if(big<=small) return big*a;else{return small*a+(big-small)*b;}}
}
ull student(ull x){ull now=upper_bound(t+1,t+1+n,x)-t;return ((now-1)*x-sum1[now-1])*c;
}
int main(){
jiasu;
cin>>a>>b>>c>>n>>m;
for(int i=1;i<=n;i++)cin>>t[i],l=min(l,t[i]);
for(int i=1;i<=m;i++)cin>>s[i],r=max(r,s[i]);
sort(t+1,t+1+n);
sort(s+1,s+1+m);
for(int i=1;i<=n;i++)sum1[i]=sum1[i-1]+t[i];
for(int i=1;i<=m;i++)sum2[i]=sum2[i-1]+s[i];
ull ans=cl(l)+student(l);
for(int k=l+1;k<=r;k++)ans=min(ans,cl(k)+student(k));
cout<<ans;return 0;
}
P8666 [蓝桥杯 2018 省 A] 三体攻击 - 洛谷
依旧二分查找+差分。
推荐记住二维差分和前缀和公式,三维就以此类推,按照下标变换的个数决定符号。
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define jiasu ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
ll a,b,c,m;
int main(){
jiasu;
cin>>a>>b>>c>>m;
ll arr[a+2][b+2][c+2],temp[a+2][b+2][c+2],la[m+1],ra[m+1],lb[m+1],rb[m+1],lc[m+1],rc[m+1],h[m+1];
for(int i=1;i<=a;i++)for(int j=1;j<=b;j++)for(int k=1;k<=c;k++)cin>>arr[i][j][k];
for(int i=1;i<=m;i++)cin>>la[i]>>ra[i]>>lb[i]>>rb[i]>>lc[i]>>rc[i]>>h[i];
ll l=0,r=m+1;
while(l+1<r){ll mid=(l+r)/2;memset(temp,0,sizeof(temp));for(int i=1;i<=mid;i++){temp[la[i]][lb[i]][lc[i]]+=h[i];temp[ra[i]+1][lb[i]][lc[i]]-=h[i];temp[la[i]][rb[i]+1][lc[i]]-=h[i];temp[la[i]][lb[i]][rc[i]+1]-=h[i];temp[ra[i]+1][rb[i]+1][lc[i]]+=h[i];temp[ra[i]+1][lb[i]][rc[i]+1]+=h[i];temp[la[i]][rb[i]+1][rc[i]+1]+=h[i];temp[ra[i]+1][rb[i]+1][rc[i]+1]-=h[i];}bool flag=true;for(int i=1;i<=a;i++){for(int j=1;j<=b;j++){for(int k=1;k<=c;k++){temp[i][j][k]=temp[i][j][k]+temp[i-1][j][k]+temp[i][j-1][k]+temp[i][j][k-1]-temp[i-1][j-1][k]-temp[i-1][j][k-1]-temp[i][j-1][k-1]+temp[i-1][j-1][k-1];if(temp[i][j][k]>arr[i][j][k]){flag=false;break;}}}}if(flag) l=mid;else r=mid;
}
cout<<r;return 0;
}
P3948 数据结构 - 洛谷
依旧差分模拟
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define jiasu ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
ll n,op,mod,mn,mx,l,r,x,d[80005],sum,ans=0,temp;
char ch;
int main(){
jiasu;
cin>>n>>op>>mod>>mn>>mx;
while(op--){cin>>ch;if(ch=='A'){cin>>l>>r>>x;d[l]+=x;d[r+1]-=x;}else{cin>>l>>r;sum=0,ans=0;for(int i=1;i<=r;i++){sum+=d[i];temp=sum*i%mod;if(i>=l&&temp>=mn&&temp<=mx) ans++;}cout<<ans<<endl;}
}
sum=0;
for(int i=1;i<=n;i++){sum+=d[i];temp=sum*i%mod;if(temp>=mn&&temp<=mx) d[i]=d[i-1]+1;else d[i]=d[i-1];
}
cin>>op;
while(op--){cin>>l>>r;cout<<d[r]-d[l-1]<<endl;
}return 0;
}
P3131 [USACO16JAN] Subsequences Summing to Sevens S - 洛谷
依旧前缀和,若(sum[i]-sum[j])%7=0,那么sum[i]%7=sum[j]%7。我们只需记录每个前缀和取余7后的值对应的最大下标和最小下标,他们的差就是最大的区间长度。注意mn[0]最小是0。
#include<bits/stdc++.h>
#define ll long long
#define ull unsigned long long
#define jiasu ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
using namespace std;
ll mx[7],mn[7],n,a,sum,ans=0;
int main(){
cin>>n;
for(ll i=1;i<=n;i++){cin>>a;sum+=a;if(mn[sum%7]==0) mn[sum%7]=i;mx[sum%7]=max(mx[sum%7],i);
}
for(int i=0;i<=6;i++){if(mn[i]!=0){ans=max(ans,mx[i]-mn[i]);}
}
cout<<max(ans,mx[0]);return 0;
}
算法竞赛太难了