牛客网多校2 farm(巧妙的随机数hash,前缀和/二维树状数组)

题目:给出一个N*M的矩阵药田,药田中每个格子都种有一种编号的为1~N*M的药,随后一个T表示有T次浇水操作,之后先是给出N行M列的矩阵(药田),再给出T行,每行有5个数,X1,Y1,X2,Y2和W,表示这次操作会在左上角为(X1,Y1),右下角为(X2,Y2)的矩阵中浇W这种药水,若是该某个药格中的药编号与被浇到的药水不同,则死亡,问你T次浇水操作后整个药田死了多少颗药?

思路:这里对每个药的编号进行随机hash得到一个大于最大编号1e6的数值,之后每次浇水操作,我们通过使用二维树状数组区间更新的巧妙办法,在已知更新的矩阵左上角和右下角情况下update四个点的值即可在O(logn*logm)时间内实现树状数组的区间更新(需要注意的是这里更新的值也是药对应药水的hash值才行).那么最终想要知道某个格子的药是否存活只需要判断他的树状数组的值%本身的hash值是否为0即可,在随机数足够优秀的条件下,能整除的情况说明该药格每次浇到的药水的是合适的(或者没有浇到任何药水),那么它是存活的,反之死亡。想法很奇妙,思路来自https://blog.youkuaiyun.com/weixin_41156591/article/details/81150890

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
typedef long long ll;
int n,m,q;
vector<ll>a[maxn],sum[maxn];
ll has[maxn];
void init()
{
    srand(time(NULL));
    for(int i=1;i<maxn-5;i++)
        has[i]=(ll)rand()*1e6+(ll)rand();//随机数hash
}
int lowbit(int x){return x&-x;}
void update(int x,int y,ll val)
{
    for(int i=x;i<=n;i+=lowbit(i))
    for(int j=y;j<=m;j+=lowbit(j))
        sum[i][j]+=val;
}
ll query(int x,int y)
{
    ll ans=0;
    for(int i=x;i>0;i-=lowbit(i))
    for(int j=y;j>0;j-=lowbit(j))
        ans+=sum[i][j];
    return ans;
}
int main()
{
    init();
    scanf("%d%d%d",&n,&m,&q);
    for(int i=1;i<=n;i++)
    {
        a[i].push_back(0);
        sum[i].push_back(0);
        for(int j=1;j<=m;j++)
        {
            int x;
            scanf("%d",&x);
            a[i].push_back(has[x]);
            sum[i].push_back(0);
        }
    }
    while(q--)
    {
        int x1,y1,x2,y2;
        int color;
        scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&color);
        update(x1,y1,has[color]);
        update(x1,y2+1,-has[color]);
        update(x2+1,y1,-has[color]);
        update(x2+1,y2+1,has[color]);
    }
    int ans=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            if(query(i,j)%a[i][j]!=0)//判断是不是有其它的药
                ans++;
        }
    printf("%d\n",ans);
    return 0;
}

但是,为什么要用树状数组维护呢?

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+10;
typedef long long ll;
int n,m,q;
vector<ll>a[maxn],sum[maxn];
ll has[maxn];
void init()
{
    srand(time(NULL));
    for(int i=1;i<maxn-5;i++)
        has[i]=(ll)rand()*1e6+(ll)rand();
}
void update(int x,int y,ll val){sum[x][y]+=val;}
int main()
{
    init();
    scanf("%d%d%d",&n,&m,&q);
    for(int i=0;i<=m;i++)//多放点0
    {
        sum[0].push_back(0);
        sum[n+1].push_back(0);
    }
    for(int i=1;i<=n;i++)
    {
        a[i].push_back(0);
        sum[i].push_back(0);
        for(int j=1;j<=m;j++)
        {
            int x;
            scanf("%d",&x);
            a[i].push_back(has[x]);
            sum[i].push_back(0);
        }
    }
    for(int i=0;i<=n+1;i++)
        sum[i].push_back(0);//再多放几个0
    while(q--)
    {
        int x1,y1,x2,y2;
        int color;
        scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&color);
        update(x1,y1,has[color]);
        update(x1,y2+1,-has[color]);
        update(x2+1,y1,-has[color]);
        update(x2+1,y2+1,has[color]);
    }
    int ans=0;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
        {
            sum[i][j]+=sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1];//
            if(sum[i][j]%a[i][j]!=0)
                ans++;
        }
    printf("%d\n",ans);
    return 0;
}

 

### DataFrame DataFrame 提供的是一个类似表的结构,由个 Series 组成,而 Series 在 DataFrame 中叫 columns [^2]。pandas 可以对不同索引的对象进行算术运算,索引与数据的对应关系仍保持在数组运算的结果中,如果没对齐的位置则补 NaN 。对于 DataFrame,对齐操作会同时发生在行和列上 [^3]。 ### 元组 元组是一种不可变的序列类型。可以存储个元素,元素可以是不同的数据类型,并且允许重复元素。例如可以建造一个二维元组 `c = ((1, 2), (2, 3), (3, 4), (4, 5))` [^4]。 ### 字典 字典是一种无序的键值对集合。字典中的键值对可以是任意类型,但键不能重复且必须是可哈希的,不能使用非 hash 类型数据作为键值,比如列表、元组。字典可以通过种方式创建,例如直接初始化 `f = {'a': 1, 'b': 2, 'c': 3}`,也可以利用元组和列表来创建 `c = ((1, 2), (2, 3), (3, 4), (4, 5)); d = [1, 2, 3, 4]; h = dict(zip(c, d))` [^4]。 ### 集合 集合是无序且唯一的数据集合。集合中的元素必须是可哈希的。集合主要用于成员检测和消除重复元素。可以使用花括号 `{}` 或 `set()` 函数来创建集合。例如: ```python s1 = {1, 2, 3} s2 = set([3, 4, 5]) ``` ### 列表 列表是 Python 中最常用的数据结构之一,它是一个有序、可变的数据集合,可以存储个元素,元素可以是不同的数据类型,并且允许重复元素。列表非常类似于 Excel 中的一列数据,但功能更加强大和灵活 [^1]。例如: ```python my_list = [1, 'hello', 3.14] ``` ### 数组 在 Python 中,一般使用 `numpy` 库来处理数组。`numpy` 数组是维的,并且元素类型通常是相同的。例如: ```python import numpy as np arr = np.array([1, 2, 3, 4]) ``` ### 序列 序列是 Python 中最基本的数据结构,包括列表、元组、字符串等。序列的特点是元素有序,可以通过索引访问。例如字符串就是一种序列: ```python s = "hello" print(s[0]) # 输出 'h' ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值