题目链接:https://vjudge.net/problem/CodeForces-514D
题目大意:现在有一排机器人(n个),每个机器人有m个属性,你可以选择一种属性进行攻击,使所有机器人的这一属性都减1,当一个机器人所有属性都小于等于0时就视为被消灭了,现在你有k次攻击的机会,请问最多能够消灭连续的多少个机器人。
思路:因为是找的连续的最大长度,(连续的……),所以想要消灭某连续区间的机器人,每种属性攻击的次数都必须达到改区段的最大值。所以这里用RMQ维护一下区间最大值,然后枚举n个起点,二分找出k次攻击最远能够消灭到哪个位置。
代码:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define mid ((l + r)>>1)
#define chl root<<1
#define chr root<<1|1
using namespace std;
typedef unsigned long long ull;
typedef long long LL;
const int manx=1e5+10;
int dp_max[manx][30][6],ans[7],len=0,mmax,m;
//dp_max[i][j][k]表示区间i~i+2^j-1的机器人第k种属性的最大值
void solve(int l,int r)
{
int pos=l-1,sum,s=l;
while(l<=r)
{
sum=0;
int k=log2(mid-s+1);
for(int i=1; i<=m; i++)
sum+=max(dp_max[s][k][i],dp_max[mid-(1<<k)+1][k][i]);//查询
if(sum<=mmax)
{
pos=mid;
l=mid+1;
}
else
r=mid-1;
}
if(pos!=s-1&&pos-s+1>len)
{
len=pos-s+1;
int k=log2(len);
for(int i=1; i<=m; i++)
ans[i]=max(dp_max[s][k][i],dp_max[pos-(1<<k)+1][k][i]);
}
}
int main()
{
int n,temp;
scanf("%d%d%d",&n,&m,&mmax);
for(int i=1; i<=n; i++)
{
for(int j=1; j<=m; j++)
{
scanf("%d",&temp);
dp_max[i][0][j]=temp;
}
}
for(int j=1; j<=20; j++)
for(int i=1; i+(1<<j)-1<=n; i++)
for(int k=1; k<=m; k++)
dp_max[i][j][k]=max(dp_max[i][j-1][k],dp_max[i+(1<<(j-1))][j-1][k]);
for(int i=1; i<=n; i++)
solve(i,n);//枚举起点
for(int i=1; i<m; i++)
printf("%d ",ans[i]);
printf("%d\n",ans[m]);
return 0;
}