Codeforces Round #291 (Div. 2) D. R2D2 and Droid Army(线段树+二分)

题目链接:https://codeforces.com/contest/514/problem/D

 

题目大意:给n个机器人,每个机器人有m个属性,可以针对每个属性都发出相应的攻击,要求总攻击<=k,而且连续被摧毁的机器人数最多,每个机器人所有的属性都变为0时视为被摧毁。

 

题目思路:建五棵线段树,分别维护各个属性,然后二分枚举连续机器人个数,暴力求解该人数情况下是否能够符合题意。

 

以下是代码:

#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<math.h>
using namespace std;
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define per(i,a,b) for(int i=a;i>=b;i--)
#define ll long long
const int MAXN = 1e5+5;
int n,m,k,pos;
int a[MAXN][5];
struct node{
    int l,r,val;
}Tree[MAXN<<2][5];
void build(int rt,int l,int r,int num){
    Tree[rt][num].l=l,Tree[rt][num].r=r;
    if(l==r){
        Tree[rt][num].val = a[l][num];
        return;
    }
    int mid=(l+r)>>1;
    build(rt<<1,l,mid,num);
    build(rt<<1|1,mid+1,r,num);
    Tree[rt][num].val=max(Tree[rt<<1][num].val,Tree[rt<<1|1][num].val);
}
int query(int rt, int l, int r, int num){
    if(Tree[rt][num].l>=l&&Tree[rt][num].r<=r){
        return Tree[rt][num].val;
    }
    int mid=(Tree[rt][num].l+Tree[rt][num].r)>>1;
    int maxx=0;
    if(l<=mid)maxx=max(query(rt<<1,l,r,num),maxx);
    if(r>mid)maxx=max(query(rt<<1|1,l,r,num),maxx);
    return maxx;
}
bool check(int x){
    rep(i,1,n-x+1){
        int temp=0;
        rep(j,0,m-1){
            temp += query(1,i,i+x-1,j);
        }
        if(temp<=k){
            pos=i;
            return true;
        }
    }
    return false;
}
int main(){
    while(~scanf("%d%d%d",&n,&m,&k)){
        rep(i,1,n){
            rep(j,0,m-1){
                scanf("%d",&a[i][j]);
            }
        }
        rep(i,0,m-1)build(1,1,n,i);
        int l=0,r=n,ans=-1;
        while(l<=r){
            int mid = (l+r)>>1;
            if(check(mid)){
                l = mid + 1;
                ans = mid;
            }
            else{
                r = mid - 1;
            }
        }
        rep(i,0,m-1){
            printf("%d ",query(1,pos,pos+ans-1,i));
        }
        printf("\n");
    }
    return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值