【CF 514D】 R2D2 and Droid Army
n个机器人 m把枪 每个怪物对应每把枪都有一定的血量 m个血槽都空机器人才挂掉
m把枪一共有k发子弹 问怎么打可以杀死最多的连续的机器人 子弹可以剩余
1~n遍历 统计当前区间最大值 如果m血槽最大值的和>k时 左边界右移一位 重新统计
输出最长序列的打法即可
这题用RMQ也可以 代码量能少点 他们还有加二分优化的 二分区间长度 就不写了。。通过这题学了学RMQ 贴一发
代码如下:
//线段树 #include <cstdio> #include <cstdio> #include <cstring> using namespace std; typedef struct Node { int m[5],next; }Node; Node tr[400040];//线段树存区间最大值 int ned[5];// int st[5]; int rg[100001][5],m; void SetTree(int site,int l,int r) { if(l == r) { for(int i = 0; i < m; ++i) tr[site].m[i] = rg[l][i]; return; } int mid = (l+r)>>1; SetTree(site<<1,l,mid); SetTree(site<<1|1,mid+1,r); for(int i = 0; i < m; ++i) tr[site].m[i] = max(tr[site<<1].m[i],tr[site<<1|1].m[i]); } void Recut(int site,int l,int r,int ll,int rr) { if(l == ll && r == rr) { for(int i = 0; i < m; ++i) { st[i] = max(st[i],tr[site].m[i]); } return; } int mid = (l+r)>>1; if(mid >= rr) Recut(site<<1,l,mid,ll,rr); else if(mid < ll) Recut(site<<1|1,mid+1,r,ll,rr); else { Recut(site<<1,l,mid,ll,mid); Recut(site<<1|1,mid+1,r,mid+1,rr); } } int main() { int n,k,i,j,kk,mlen,sum; scanf("%d %d %d",&n,&m,&kk); for(i = 1; i <= n; ++i) for(k = 0; k < m; ++k) scanf("%d",&rg[i][k]); SetTree(1,1,n); sum = mlen = 0; memset(st,0,sizeof(st)); for(i = 1,j = 1; i <= n; ++i) { for(k = 0; k < m; ++k) { if(rg[i][k] > st[k]) { sum += rg[i][k]-st[k]; st[k] = rg[i][k]; } } while(sum > kk) { if(j == i) { sum = 0; memset(st,0,sizeof(st)); j++; break; } for(k = 0; k < m; ++k) { if(rg[j][k] == st[k]) { memset(st,0,sizeof(st)); Recut(1,1,n,j+1,i); sum = 0; for(k = 0; k < m; ++k) sum += st[k]; break; } } ++j; } if(i-j+1 > mlen) { mlen = i-j+1; for(k = 0; k < m; ++k) ned[k] = st[k]; } } for(i = 0; i < m; ++i) { if(i) putchar(' '); printf("%d",ned[i]); } puts(""); return 0; }
//RMQ #include <iostream> #include <cstdio> #include <cstring> #include <cmath> using namespace std; int rq[100001][18][5]; int ned[5]; int st[5]; int m,n; void Init() { int i,j,k; for(j = 1; (1<<j) <= n; ++j) for(i = 1; i <= n; ++i) if(i + (1<<j) -1 <= n) for(k = 0; k < m; ++k) rq[i][j][k] = max(rq[i][j-1][k],rq[i+(1<<(j-1))][j-1][k]); } int main() { int k,i,j,kk,mlen,sum,t; scanf("%d %d %d",&n,&m,&kk); sum = mlen = 0; memset(st,0,sizeof(st)); for(i = 1,j = 1; i <= n; ++i) { for(k = 0; k < m; ++k) { scanf("%d",&rq[i][0][k]); } } Init(); for(i = 1,j = 1; i <= n; ++i) { for(k = 0; k < m; ++k) { if(rq[i][0][k] > st[k]) { sum +=rq[i][0][k]-st[k]; st[k] = rq[i][0][k]; } } while(sum > kk) { if(j == i) { sum = 0; memset(st,0,sizeof(st)); j++; break; } for(k = 0; k < m; ++k) { if(rq[j][0][k] == st[k]) { memset(st,0,sizeof(st)); sum = 0; for(k = 0; k < m; ++k) { t = log10(i-j)/log10(2); st[k] = max(rq[j+1][t][k],rq[i-(1<<t)+1][t][k]); sum += st[k]; } break; } } ++j; } if(i-j+1 > mlen) { mlen = i-j+1; for(k = 0; k < m; ++k) ned[k] = st[k]; } } for(i = 0; i < m; ++i) { if(i) putchar(' '); printf("%d",ned[i]); } puts(""); return 0; }