分析
乱搞题。
考虑将区间 \([l,r]\) 中所有人干掉的代价。设 \(cnt_{i}=\max\limits_{j=l}^{r}a_{j,i}\),则代价为:\(\sum\limits_{i=1}^{m}cnt_i\)。很显然,只有在 \(\sum\limits_{i=1}^{m}cnt_i \le k\) 是,我们才能将这些人全部干掉。
考虑枚举右端点 \(r\),与每个 \(r\) 对应的最小能干掉的区间左端点 \(l\)。不难发现随着区间的缩进,\(cnt_i\) 的值是不增的,所以完全可以使用指针求出 \(l\),复杂度是 \(O(n)\) 的。而在指针移动的时候,\(cnt_i\) 的值不方便直接计算,但注意到范围:\(m \le 5\),这可以用线段树乱搞维护。总的复杂度是 \(O(n \log n)\)(\(m\) 忽略不计)。
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define re register
#define il inline
const int N=1e5+10,M=10;
struct node{
int s[M];
}a[N];
int n,m,k;
struct tree{
int l,r,mx[M];
}tr[N<<2];
int ANS[M];
il void up(int now){
tr[now].mx[1]=max(tr[now<<1].mx[1],tr[now<<1|1].mx[1]);
tr[now].mx[2]=max(tr[now<<1].mx[2],tr[now<<1|1].mx[2]);
tr[now].mx[3]=max(tr[now<<1].mx[3],tr[now<<1|1].mx[3]);
tr[now].mx[4]=max(tr[now<<1].mx[4],tr[now<<1|1].mx[4]);
tr[now].mx[5]=max(tr[now<<1].mx[5],tr[now<<1|1].mx[5]);
return ;
}
il tree get(tree a,tree b){
tree ans={0,0,0,0,0,0,0};
ans.mx[1]=max(a.mx[1],b.mx[1]);
ans.mx[2]=max(a.mx[2],b.mx[2]);
ans.mx[3]=max(a.mx[3],b.mx[3]);
ans.mx[4]=max(a.mx[4],b.mx[4]);
ans.mx[5]=max(a.mx[5],b.mx[5]);
return ans;
}
il void build(int now,int l,int r){
tr[now].l=l,tr[now].r=r;
if(l==r){
tr[now].mx[1]=a[l].s[1];
tr[now].mx[2]=a[l].s[2];
tr[now].mx[3]=a[l].s[3];
tr[now].mx[4]=a[l].s[4];
tr[now].mx[5]=a[l].s[5];
return ;
}
int mid=l+r>>1;
build(now<<1,l,mid),build(now<<1|1,mid+1,r);
up(now);
return ;
}
il tree query(int now,int l,int r){
if(tr[now].l>=l&&tr[now].r<=r) return tr[now];
tree ans={0,0,0,0,0,0,0};int mid=tr[now].l+tr[now].r>>1;
if(l<=mid) ans=get(ans,query(now<<1,l,r));
if(mid<r) ans=get(ans,query(now<<1|1,l,r));
return ans;
}
il void solve(){
cin>>n>>m>>k;
for(re int i=1;i<=n;++i){
for(re int j=1;j<=m;++j){
cin>>a[i].s[j];
}
}
build(1,1,n);
int maxx=0;
for(re int i=1,l=1;i<=n;++i)
while(l<=i){
tree now=query(1,l,i);
int sum=now.mx[1]+now.mx[2]+now.mx[3]+now.mx[4]+now.mx[5];
if(sum<=k){
if(i-l+1>maxx)
ANS[1]=now.mx[1],ANS[2]=now.mx[2],ANS[3]=now.mx[3],ANS[4]=now.mx[4],ANS[5]=now.mx[5],
maxx=i-l+1;
break;
}
else l++;
}
for(re int i=1;i<=m;++i){
cout<<ANS[i]<<" ";
}
return ;
}
signed main(){
solve();
return 0;
}
标签:cnt,Droid,Army,int,题解,re,ANS,now,mx
From: https://www.cnblogs.com/harmisyz/p/18058656