2018 牛客多校第二场 J farm (随机+二维前缀处理)(二进制)

题目链接:https://www.nowcoder.com/acm/contest/140/J

题意:

给你N*M个矩阵,每个格子里有种类为k的花。给你t次操作,每次在一个子矩阵里施肥,如果种类为k的肥料被施到不同种类的花上,花就死掉。最后问你死了多少花。

思路:

我们把施肥在同一个矩阵里的种类的肥料加起来,整除以花的种类,如果能整除,说明有可能不会死,但是大多数情况还是错的,如k=5的话,施一次3号肥和一次2号肥也是死的,所以我们可以给花随机一个很大的权值,这个情况就有较大概率避免了。在用二维前缀和处理一波即可。

#include<bits/stdc++.h>
using namespace std;
const int N=1e6+10;
#define ll long long
ll hh[N];
ll k;
int main()
{
    int n,m,t;
    int x1,x2,y1,y2;
    srand(time(0));
    scanf("%d%d%d",&n,&m,&t);
    for(int i=1;i<=n*m;i++)
    {
        hh[i]=1e6+i*rand()+1001;;
    }
    ll **a=new ll *[n+5];
    ll **b=new ll *[n+5];
    for(int i=0;i<n+5;i++)
    {
        a[i]=new ll[m+5];
        b[i]=new ll[m+5];
    }
    for(int i=0;i<=n+1;i++)
    {
        for(int j=0;j<=m+1;j++)
        {
            a[i][j]=b[i][j]=0;
        }
    }
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            scanf("%lld",&b[i][j]);
            b[i][j]=hh[b[i][j]];
        }
    }
    while(t--)
    {
        scanf("%d%d%d%d%lld",&x1,&y1,&x2,&y2,&k);
        k=hh[k];
        a[x1][y1]+=k;
        a[x1][y2+1]-=k;
        a[x2+1][y1]-=k;
        a[x2+1][y2+1]+=k;
    }
  
    ll ans=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
  
            a[i][j]+=a[i][j-1]+a[i-1][j]-a[i-1][j-1];
            //cout<<a[i][j]<<' '<<' '<<endl;
            if(a[i][j]%b[i][j]!=0)ans++;
        }
    }
    printf("%lld\n",ans);
    return 0;
}

思路:

将每一个农田上的数字看成2进制,如果多次施肥中同一块农田上施肥的种类不同,那么这些数字必有一位二进制数不同。先统计每一块农田被使了多少次肥。即统计每一块农田,二进制的每一位有多少个0和1。然后按位遍历,若0,1同时出现,则植物死亡。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e6+10;
int n,m,t;
int x1[N],Y1[N],x2[N],y2[N],num[N],a[N],b[N],ans[N],c[N];
int id(int x,int y)
{
    return (x-1)*m+y;
}
 
void add(int i,int *s)
{
    s[id(x1[i],Y1[i])]++;
    if(y2[i]+1<=m) s[id(x1[i],y2[i])+1]--;
    if(x2[i]+1<=n) s[id(x2[i]+1,Y1[i])]--;
    if(x2[i]+1<=n&&y2[i]+1<=m)
        s[id(x2[i]+1,y2[i]+1)]++;
}
void work(int *s)
{
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(j>1) s[id(i,j)]+=s[id(i,j-1)];
            if(i>1) s[id(i,j)]+=s[id(i-1,j)];
            if(i>1&&j>1) s[id(i,j)]-=s[id(i-1,j-1)];
        }
    }
}
 
int main()
{
 
    scanf("%d%d%d",&n,&m,&t);
 
    for(int i=1;i<=n*m;i++)
    {
        scanf("%lld",&a[i]);
    }
    for(int i=1;i<=t;i++)
    {
        scanf("%d%d%d%d%d",&x1[i],&Y1[i],&x2[i],&y2[i],&num[i]);
        add(i,b);
    }
   work(b);
    for(int u=0;u<=20;u++)
    {
        memset(c,0,sizeof(c));
        for(int i=1;i<=t;i++)
        {
            if((num[i]>>u)&1)
              {
                   add(i,c);
              }
        }
       work(c);
        for(int i=1;i<=n*m;i++)
        {
                bool f;
                if((a[i]>>u)&1)
                f=true;
                else f=false;
                if(f)
                {
                    if(b[i]>c[i])ans[i]=1;
                }
                else
                {
                    if(c[i])ans[i]=1;
                }
        }
    }
    int sum=0;
        for(int i=1;i<=n*m;i++)
        {
            if(ans[i])sum++;
 
        }
        printf("%d\n",sum);
    return 0;
}

猜你喜欢

转载自blog.csdn.net/imzxww/article/details/81194446