【CF 514D】 R2D2 and Droid Army (线段树、RMQ)

来源:互联网 发布:怎么做图书marc数据 编辑:程序博客网 时间:2024/05/01 15:18

【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;}


0 0
原创粉丝点击