J-farm
思路:随机算法,二维BIT
一开始考虑的做法和题解的随机做法想的一样,但是没想到离散化...我都不知道那几个小时在干嘛。
对于每一个权值的化肥,我们随意rand一个值,每次操作的时候这个区间就加上这个值。如果最后对于i,j。倘若cnt[i][j]*mp[a[i][j]]==v[i][j]。 那么在很大程度上可以确定,都是一个种类的化肥,该植物不会死
在这种Full-Back机制下的比赛,随机算法是很优秀的做法。打多了cf这种有HACK机制的比赛,很多时候忽略了随机算法的作用
关于二维BIT的区间更新,有2种写法,个人建议用下面的板子用差分标记,再去O(n*m)求SUM。 倘若用另一种板子,复杂度O(n*m*(logn)*(logn))T了。
#include<bits/stdc++.h>
#define PI acos(-1.0)
#define pb push_back
#define F first
#define S second
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int N=1e6+6;
const int MOD=1e9+7;
template <class T>
bool sf(T &ret){ //Faster Input
char c; int sgn; T bit=0.1;
if(c=getchar(),c==EOF) return 0;
while(c!='-'&&c!='.'&&(c<'0'||c>'9')) c=getchar();
sgn=(c=='-')?-1:1;
ret=(c=='-')?0:(c-'0');
while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');
if(c==' '||c=='\n'){ ret*=sgn; return 1; }
while(c=getchar(),c>='0'&&c<='9') ret+=(c-'0')*bit,bit/=10;
ret*=sgn;
return 1;
}
int n,m,T;
//int a[N];
int mp[N];
vector<int> a[N];
vector<ll> sum[N];
vector<int> cnt[N];
void add(int x,int y,int val,int v2){ // 更新
// cout <<"here" << endl;
sum[x][y]+=val,cnt[x][y]+=v2;
}
ll getsum(int x,int y){ // 单点求值 等价 求区间前缀和
ll res=0;
for(int i=x;i;i-=i&(-i))
for(int j=y;j;j-=j&(-j))
res+=sum[i][j];
return res;
}
void update(int x1,int y1,int x2,int y2,int val,int v2){
add(x1,y1,val,v2);// 结论
add(x2+1,y2+1,val,v2);
add(x1,y2+1,-val,-v2);
add(x2+1,y1,-val,-v2);
}
int main(void){
sf(n);sf(m);sf(T);
for(int i=0;i<=n+5;i++) a[i].resize(m+5),cnt[i].resize(m+5),sum[i].resize(m+5);
// for(int i=0;i<=0;i++){
// for(int j=0;j<=m+4;j++) sum[i][j]=cnt[i][j]=0;
// }
// cout <<"here" << endl;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++) sum[i][j]=cnt[i][j]=0,sf(a[i][j]);
for(int i=1;i<=n*m;i++) mp[i]=i;
random_shuffle(mp+1,mp+1+n*m);
for(int i=1;i<=T;i++){
int x1,y1,x2,y2,k;
sf(x1),sf(y1),sf(x2),sf(y2),sf(k);
update(x1,y1,x2,y2,mp[k],1);
}
int ans=0;
for (int i=1;i<=n;i++){
for (int j=1;j<=m;j++){
// cout <<i <<" "<<j<<endl;
sum[i][j]=sum[i][j]-sum[i-1][j-1]+sum[i][j-1]+sum[i-1][j];
cnt[i][j]=cnt[i][j]-cnt[i-1][j-1]+cnt[i][j-1]+cnt[i-1][j];
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
if(sum[i][j]==1ll*mp[a[i][j]]*cnt[i][j]) ans++;
}
}
printf("%lld\n",1ll*n*m-ans);
return 0;
}