Codeforces #291 (Div. 2) D. R2D2 and Droid Army(RMQ+二分)

题意:

有n*m的矩阵,然后你有k发子弹。现在你可以朝着任意列发射子弹,每一发子弹都会使该列上的数值-1,最小减少到0。

现在问你连续最长的行数,在k发子弹内,使得这些行上的数值全部为0.

思路:

简单的二分枚举最长行数区间,每个区间的最大值决定了要发射的子弹数,,所以是RMQ问题,当然这里的枚举全部枚举,用尺取法也可以。

//889 ms#include<cstdio>#include<algorithm>#include<cstring>#include<iostream>#define M 100005#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1#define root 1,n,1using namespace std;int n,m,lim;int Max[6][M<<2];int shots[6];void pushup(int rt){for(int i=1;i<=m;i++){Max[i][rt]=max(Max[i][rt<<1],Max[i][rt<<1|1]);}}void build(int l,int r,int rt){if(l==r){for(int i=1;i<=m;i++){scanf("%d",&Max[i][rt]);}return ;}int m=(l+r)>>1;build(lson);build(rson);pushup(rt);}int query(int*Max,int L,int R,int l,int r,int rt){if(L<=l&&r<=R){return Max[rt];}int m=(l+r)>>1;int q1=-1,q2=-1;if(L<=m) q1=query(Max,L,R,lson);if(R>m) q2=query(Max,L,R,rson);return max(q1,q2);}bool ok(int x){int cnt=0;for(int j=1;j+x-1<=n;j++){cnt=0;for(int k=1;k<=m;k++){int p=query(Max[k],j,j+x-1,root);cnt+=p;}if(cnt<=lim) return true;}return false;}int main(){scanf("%d%d%d",&n,&m,&lim);build(root);int lb=0,ub=n+1;while(ub-lb>1){ //二分出最大区间长度int mid=(ub+lb)>>1;if(ok(mid)){lb=mid;}else ub=mid;}for(int j=1;j+lb-1<=n&&lb;j++){//当lb=0的时候说明一个机器人也破坏不了,这个时候不能再查询,否则会REint cnt=0;for(int k=1;k<=m;k++){int p=query(Max[k],j,j+lb-1,root);cnt+=p;shots[k]=p;}if(cnt<=lim)break;}printf("%d",shots[1]);for(int i=2;i<=m;i++){printf(" %d",shots[i]);}puts("");return 0;}

空虚无聊的时候就读书,但一定得有自己的生活目标和计划。

Codeforces #291 (Div. 2) D. R2D2 and Droid Army(RMQ+二分)

相关文章:

你感兴趣的文章:

标签云: