CF514D R2D2 and Droid Army 题解

分析

乱搞题。

考虑将区间 \([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;
}
posted @ 2024-03-07 13:09  harmis_yz  阅读(9)  评论(0)    收藏  举报