题解 CF514D 【R2D2 and Droid Army】
题意
一共有N个人,每个人有M个属性值,
当一个人的所有属性值都小于等于0的时候,这个人就算被销毁了。
我们每次操作可以选一种属性值进行攻击,
使得所有人的这个属性的值都-1.
我们最多可以进行K次操作,
问我们最多可以干掉多少个连续的人。
问这种时候的具体操作(每一种属性用了多少次操作)
\(n \le 10^5 \ m \le 5 \ k \le 10^9\)
解法
二分干掉的连续人数
直接枚举每个长度为mid的区间
单调队列求区间最大值。
当所有 各属性的区间最大值 的和 \(sum \le K\) 时,存在方案干掉 \(mid\) 个人。
复杂度\(O(nlogn)\)
#include<bits/stdc++.h>
using namespace std;
#define rep(i,x,y) for(int i=x;i<=y;i++)
#define per(i,x,y) for(int i=x;i>=y;i--)
#define rd(x) scanf("%d",&x);
typedef long long LL;
const int N=1e5+10,M=7;
int n,m,hd[M],tl[M],a[N][M],qaq[M],maxx[M];
LL k;
int check(int len){
rep(i,1,m) hd[i]=1,tl[i]=0;
int q[M][N];memset(q,0,sizeof(q));
int p[M][N];memset(p,0,sizeof(p));
rep(i,1,n){
LL sum=0;
rep(j,1,m){
while(hd[j]<=tl[j]&&q[j][tl[j]]<=a[i][j]) tl[j]--;
q[j][++tl[j]]=a[i][j],p[j][tl[j]]=i;
while(hd[j]<=tl[j]&&p[j][hd[j]]<=i-len) hd[j]++;
if(i>=len) sum+=q[j][hd[j]],maxx[j]=q[j][hd[j]];
}
if(i>=len&&sum<=k){
rep(j,1,m) qaq[j]=maxx[j];
qaq[m]+=k-sum;return 1;
}
}
return 0;
}
int main(){
rd(n);rd(m);scanf("%lld",&k);
rep(i,1,n) rep(j,1,m)
rd(a[i][j]);
int l=0,r=n,ans;
while(l<=r){
int mid=(l+r)>>1;
if(check(mid)) ans=mid,l=mid+1;
else r=mid-1;
}
rep(i,1,m) printf("%d ",qaq[i]);
return 0;
}
恭喜,一道水紫!
QwQwQ