学算法——RMQ+二分
扫描二维码
随时随地手机看文章
【CF简介】
提交链接:CF 514D
题面:
D. R2D2 and Droid Army time limit per test 2 seconds memory limit per test 256 megabytes input standard input output standard output
An army of n droids is lined up in one row. Each droid is described bym integers a1, a2, ..., am, whereai is the number of details of thei-th type in this droid's mechanism. R2-D2 wants to destroy the sequence of consecutive droids of maximum length. He hasm weapons, the i-th weapon can affect all the droids in the army by destroying one detail of thei-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 mostk 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 containsm integers a1, a2, ..., am (0 ≤ ai ≤ 108), where ai is the number of details of thei-th type for the respective robot.
Output
Print m space-separated integers, where thei-th number is the number of shots from the weapon of thei-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项属性,每个机器人的每项属性并不统一。要消灭一个机器人,需要将他的每项属性值都减为1,现在有k次操作机会,每次操作可以将每个机器人的某项属性值都减1,问在不超过k次操作的情况下,如何分配每项属性减几次,可以使得最终消灭最多的连续机器人序列,输出分配攻击方案。
注意:如果不能全部消灭,则每项输出0,因为要求消耗尽量少的操作数,达到杀死尽量多连续的机器人。
解题:
RMQ,区间询问问题,可以做到O(nlogn)复杂度预处理,O(log n)复杂度询问,入门ST算法,可以看这篇博客,通过RMQ预处理好每项属性,区间最大值。
随后询问时,只要查询出该区间每项属性的最大值,随后将这些最大值累加,即为消灭该区间全部机器人的最小操作次数。
枚举左端点,二分右区间,若区间需要操作数大于k,则左移右区间,缩小区间长度,若小于等于k则,右移右区间,增大区间长度。在二分过程中更新区间最优值,同时还需记录此时的分配情况,若区间长度相等的情况下,还需保证操作数尽量小。
代码:
#include#include#include#include#include#include#include#include#define LL long long #define maxn 100010 #define sq(a) 1LL*(a)*(a) #define mod 1000000007 using namespace std; int arr[maxn][5],d[maxn][5][20],path[5],tmp[5]; int n,m,k; void init() { for(int i=0;i<n;i++) for(int j=0;j<m;j++) d[i][j][0]=arr[i][j]; for(int j=1;(1<<j)<=n;j++) for(int i=0;i+(1<<j)-1<n;i++) for(int k=0;k<m;k++) d[i][k][j]=max(d[i][k][j-1],d[i+(1<<(j-1))][k][j-1]); } int RMQ(int le,int ri) { int k=0,res=0; for(int i=0;i<m;i++) { k=0; while((1<<(k+1))<=ri-le+1) k++; tmp[i]=max(d[le][i][k],d[ri-(1<<k)+1][i][k]); res+=tmp[i]; } return res; } void update() { for(int j=0;j<m;j++) path[j]=tmp[j]; } int main() { int le,ri,temp,ans=0,ansk=0x3f3f3f3f; bool flag=0; scanf("%d%d%d",&n,&m,&k); for(int i=0;i<n;i++) for(int j=0;j<m;j++) scanf("%d",&arr[i][j]); init(); for(int i=0;i<n;i++) { le=i; ri=n-1; if(ri-le+1<ans) break; while(le>1; temp=RMQ(i,mid); if(tempans) { ansk=temp; ans=mid-i+1; update(); } else if(mid-i+1==ans) { if(ansk>temp) { ansk=temp; update(); } } le=mid+1; } else { ri=mid-1; if(ri-i+1<ans) break; } } } printf("%d",path[0]); for(int i=1;i<m;i++) printf(" %d",path[i]); printf("n"); return 0; }