牛客每日练习----可做题,汀博尔,轰炸区最优选取

大提琴的声音就像一条河,左岸是我无法忘却的回忆,右岸是我值得紧握的璀璨年华,中间流淌的,是我年年岁岁淡淡的感伤

链接:https://ac.nowcoder.com/acm/problem/14500
来源:牛客网
 

题目描述

qmqmqm希望给sublinekelzrip出一道可做题。于是他想到了这么一道题目:给一个长度为n的非负整数序列ai,你需要计算其异或前缀和bi,满足条件b1=a1,bi=bi-1 xor ai(i >= 2).

但是由于数据生成器出现了问题,他生成的序列a的长度特别长,并且由于内存空间不足,一部分ai,已经丢失了,只剩余m个位置的元素已知。现在qmqmqm找到你,希望你根据剩余的ai,计算出所有可能的a序列对应的b序列中∑i=1nbi\sum_{i=1}^n b_i∑i=1n​bi​的最小值。

输入描述:

输入第一行两个非负整数n,m,分别表示原始序列a的长度及剩余元素的个数。

之后m行,每行2个数i,ai,表示一个剩余元素的位置和数值。

输出描述:

输出一个整数表示可能的最小值。

示例1

输入

复制

5 3
4 0
3 7
5 0

输出

复制

7

说明

已知的a序列为:X,X,7,0,0,其中`X`表示这个位置丢失了。一种可能的a序列为0,7,7,0,0,对应的b序列为0,7,0,0,0,和最小为7。可以证明不存在和更小的情况。

备注:

1≤n≤109,0≤m≤min{n,105},0≤ai≤109
注意未知的 ai 可以超过已知 ai的范围。

保证输入中所有的 i 不同,且满足 1≤i≤n
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <ctime>
#include <cctype>
#include <bitset>
#include <utility>
#include <sstream>
#include <complex>
#include <iomanip>
#define inf 1000000000
typedef long long ll;
using namespace std;
int n,m,b[300010],pre;
ll ans,f[300010][2];
struct node
{
    int id;
    int val;
} a[300010];
bool cmp(node a,node b)
{
    return a.id<b.id;
}
int main()
{
    cin>>n>>m;
    n=0;
    for (int i=1; i<=m; i++)
        cin>>a[i].id>>a[i].val;
    sort(a+1,a+m+1,cmp);
    for (int i=1; i<=m; i++)
    {
        if (a[i].id-pre-1>=2)
        {
            b[++n]=-1;
            b[++n]=-1;
            b[++n]=a[i].val;
        }
        else if(a[i].id-pre==2)
        {
            b[++n]=-1;
            b[++n]=a[i].val;
        }
        else
            b[++n]=a[i].val;
        pre=a[i].id;
    }
    f[0][1]=1e15;
    f[0][0]=0;
    for (int p=0; p<=30; p++)
    {
        for (int i=1; i<=n; i++)
            if (b[i]<0)
            {
                f[i][1]=min(f[i-1][0]+(1<<p),f[i-1][1]+(1<<p));
                f[i][0]=min(f[i-1][1],f[i-1][0]);
            }
            else
            {
                if (b[i]&(1<<p))
                {
                    f[i][1]=f[i-1][0]+(1<<p);
                    f[i][0]=f[i-1][1];
                }
                else
                {
                    f[i][1]=f[i-1][1]+(1<<p);
                    f[i][0]=f[i-1][0];
                }
            }
        ans+=min(f[n][0],f[n][1]);
    }
    printf("%lld",ans);
    return 0;
}

链接:https://ac.nowcoder.com/acm/problem/14504
来源:牛客网
 

题目描述

有 n 棵树,初始时每棵树的高度为 Hi,第 i 棵树每月都会长高 Ai。现在有个木料长度总量为 S 的订单,客户要求每块木料的长度不能小于L,而且木料必须是整棵树(即不能为树的一部分)。现在问你最少需要等多少个月才能满足订单。

输入描述:

第一行 3 个用空格隔开的非负整数 n,S,L,表示树的数量、订单总量和单块木料长度限制。
第二行 n 个用空格隔开的非负整数,依次为 H1,H2,... ,Hn。
第三行 n 个用空格隔开的非负整数,依次为 A1,A2,... ,An。

输出描述:

输出一行一个整数表示答案。

示例1

输入

复制

3 74 51
2 5 2
2 7 9

输出

复制

7

说明

对于样例,在六个月后,各棵树的高度分别为 14,47,56,此时无法完成订单。
在七个月后,各棵树的高度分别为 16,54,65,此时可以砍下第 2 和第 3 棵树完成订单了。

备注:

1≤n≤200000,1≤S,L≤1018,1≤Hi,Ai≤109
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <ctime>
#include <cctype>
#include <bitset>
#include <utility>
#include <sstream>
#include <complex>
#include <iomanip>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
ll a[200010],h[200010],n,l,r,mid,mx,S,L;
bool check(ll month)
{
    ll sum=0;
    for(int i=1; i<=n; i++)
    {
        if(h[i]+month*a[i]>=L)
            sum+=h[i]+month*a[i];
        if(sum>=S)
            return false;
    }
    return true;
}
int main()
{
    ios::sync_with_stdio(false);
    cin>>n>>S>>L;
    for(int i=1; i<=n; i++)
        cin>>h[i];
    for(int i=1; i<=n; i++)
        cin>>a[i],mx=max(mx,a[i]);
    l=0,r=1e18/mx;
    while(l<=r)
    {
        mid=(l+r)/2;
        if(check(mid))
            l=mid+1;
        else
            r=mid-1;
    }
    cout<<l<<endl;
    return 0;
}

链接:https://ac.nowcoder.com/acm/problem/14505
来源:牛客网
 

题目描述

现在给出一个正方形地图,其边长为n,地图上有的地方是空的,有的地方会有敌人。

我们现在有一次轰炸敌人的机会,轰炸敌人的区域是一个k*k的正方形区域,现在需要你解决的问题就是计算最多轰炸的敌人数量是多少。 

输入描述:

本题包含多组数据,每组数据第一行输入两个数n,k。
接下来n行,每行n个数字,表示这个点上的敌人数量。
数据范围:
1<=n<=50
1<=k<=n
每个点上的敌人数量不超过100个(0<=a[i][j]<=100)。

输出描述:

每组数据输出包含一行,表示计算的结果。

示例1

输入

复制

4 2
1 1 0 0
1 1 0 0
0 0 2 2
0 0 2 2

输出

复制

8

说明

样例中,显然轰炸右下角那个部分能够击败最多的敌人
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <vector>
#include <ctime>
#include <cctype>
#include <bitset>
#include <utility>
#include <sstream>
#include <complex>
#include <iomanip>
#define inf 0x3f3f3f3f
typedef long long ll;
using namespace std;
int n,k,mp[60][60];
bool judge(int x,int y)
{
    if(x>=1&&x+k-1<=n&&y>=1&&y+k-1<=n)
        return true;
    return false;
}
int dfs(int x,int y)
{
    int ls=0;
    if(judge(x,y))
    {
        for(int i=x; i<=x+k-1; i++)
            for(int j=y; j<=y+k-1; j++)
                ls+=mp[i][j];
    }
    return ls;
}
int main()
{
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        int jg=0;
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                cin>>mp[i][j];
        for(int i=1; i<=n; i++)
            for(int j=1; j<=n; j++)
                jg=max(jg,dfs(i,j));
        cout<<jg<<endl;
    }
    return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值