CodeForces - 514D (線段樹+二分)

An army of n droids is lined up in one row. Each droid is described by m integers a1, a2, …, am, where ai is the number of details of the i-th type in this droid’s mechanism. R2-D2 wants to destroy the sequence of consecutive droids of maximum length. He has m weapons, the i-th weapon can affect all the droids in the army by destroying one detail of the i-th type (if the droid doesn’t have details of this type, nothing happens to it).

A droid is considered to be destroyed when all of its details are destroyed. R2-D2 can make at most k shots. How many shots from the weapon of what type should R2-D2 make to destroy the sequence of consecutive droids of maximum length?

Input
The first line contains three integers n, m, k (1 ≤ n ≤ 105, 1 ≤ m ≤ 5, 0 ≤ k ≤ 109) — the number of droids, the number of detail types and the number of available shots, respectively.

Next n lines follow describing the droids. Each line contains m integers a1, a2, …, am (0 ≤ ai ≤ 108), where ai is the number of details of the i-th type for the respective robot.

Output
Print m space-separated integers, where the i-th number is the number of shots from the weapon of the i-th type that the robot should make to destroy the subsequence of consecutive droids of the maximum length.

If there are multiple optimal solutions, print any of them.

It is not necessary to make exactly k shots, the number of shots can be less.

Examples
input

5 2 4
4 0
1 2
2 1
0 2
1 3

output

2 2

input

3 2 4
1 2
1 3
2 2

output

1 3

Note
In the first test the second, third and fourth droids will be destroyed.

In the second test the first and second droids will be destroyed.

題目大意:給出n個機器人,每個機器人有m個屬性,我們可以使用一個武器來破壞所有機器人的某一個屬性,然後問我們最多開K槍的情況下,我們可以破壞的最長的連續機器人,然後輸出我們的方案。

解題思路:我們觀察得到m是很小的一個數(m<=5),所以我們可以用一個線段樹來維護這m個數,然後我們二分枚舉區間來得到這個區間中的每個屬性的最大值,然後我們使得這個區間的機器人的所有屬性都變爲0,就需要開每個屬性的最大值的和,判斷一下這個值是否小於等於K即可。
但是打排位賽的時候題意讀錯了,本來一個很簡單的二分加線段樹,因爲我題意都沒讀懂,就一直沒有動手敲。
代碼:

#pragma GCC optimize(2)
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <bitset>
#include <queue>
//#include <random>
#include <time.h>
using namespace std;
#define int long long
#define ls root<<1
#define rs root<<1|1
const int maxn = 1e5 + 7;
//std::mt19937 rnd(time(NULL));
struct 
{
    int date[5];
    int l, r;
}t[maxn<<2];
int n, m, ans[10], tmp[10], k;
void build(int root,int l,int r)
{
    t[root].l = l, t[root].r = r;
    if(l==r){
        for (int i = 0; i < m;i++){
            scanf("%lld", &t[root].date[i]);
        }
        return;
    }
    int mid = l + r >> 1;
    build(ls, l, mid);
    build(rs, mid+1, r);
    for (int i = 0; i < m;i++)
        t[root].date[i] = max(t[ls].date[i], t[rs].date[i]);
}
void query(int root,int l,int r)
{
    if(t[root].l>=l && t[root].r<=r){
        for (int i = 0; i < m;i++){
            tmp[i] = max(tmp[i], t[root].date[i]);
        }
        return;
    }
    int mid = t[root].l + t[root].r >> 1;
    if(l<=mid)
        query(ls, l, r);
    if(r>mid)
        query(rs, l, r);
}
bool check(int len){
    for (int i = 1; i + len <= n + 1;i++){
        memset(tmp, 0, sizeof tmp);
        query(1, i, i + len - 1);
        int res = 0;
        for (int j = 0; j < m;j++){
            res += tmp[j];
        }
        if(res<=k)
            return true;
    }
    return false;
}
signed main()
{
    scanf("%lld%lld%lld", &n, &m, &k);
    build(1, 1, n);
    int l = 1, r = n;
    while(l<=r){
        int mid = l + r >> 1;
        if(check(mid)){
            memcpy(ans, tmp, sizeof tmp);
            l = mid + 1;
        }
        else
            r = mid - 1;
    }
    for (int i = 0; i < m;i++){
        printf("%lld ", ans[i]);
    }
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章