(一)题面:
题目描述
White Cloud placed n containers in sequence on a axes. The i-th container is located at x[i] and there are a[i] number of products in it.
White Rabbit wants to buy some products. The products which are required to be sold must be placed in the same container.
The cost of moving a product from container u to container v is 2*abs(x[u]-x[v]).
White Cloud wants to know the maximum number of products it can sell. The total cost can't exceed T.
输入描述:
The first line of input contains 2 integers n and T(n <= 500000,T <= 1000000000000000000)
In the next line there are n increasing numbers in range [0,1000000000] denoting x[1..n]
In the next line there are n numbers in range[0,10000] denoting a[1..n]
输出描述:
Print an integer denoting the answer.
示例1
输入
2 3
1 2
2 3
输出
4
(二)题意:
给定一个n*m的矩阵,给出矩阵中每一个位置的初始值,给定T次操作,每次操作给出一个子矩阵及一个值val,需要将该子矩阵中的每一个位置的值替换为val,问在操作T次以后,原矩阵中有多少个位置上的值改变过至少一次。
(三)题解:
①现将原操作中的替换操作视作加操作,那么经过T操作以后,如果某个位置上的值只与与初始值相等的值相加过,那么最后相加以后的结果一定是初始值的整倍数。那么如果与不想等的值相加过呢?结果是不确定的,比如某个位置上的初始值为3,然后该位置上先后加了1、2,那么最终得到的结果也是初始值3的整倍数。为了尽可能避免这种情况,我们可以为每一个初始值重新映射一个值,这样处理以后虽然仍然会有错误的可能,但是几率就比较小了。接着就是求一个二维前缀和查询即可。复杂度O(n*m)。
②官方题解是将每一个值化成一个二进制串处理,如果两个值不想等,那么这两个值的二进制位上至少有一个不相同,那么我们统计一下每一个位置的每一个二进制位上被0覆盖和被1覆盖的次数,这个求一次二维前缀和也可统计。如果原来的数字为0,而现在有1覆盖过,那么肯定被不同的数覆盖过,同理如果原来为1,而被0覆盖过,则也是被不同的数覆盖过。这种做法和上述做法有一定的相似,但是结果一定是对的。复杂度O(n*m+T)log(n*m)。
(四)代码:
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<ctime>
#include<algorithm>
#define LL long long
using namespace std;
const int maxn=1e6+10;
int n,m,k,x1,Y1,x2,y2,z;
LL Hash[maxn];
int main(){
srand(time(0));
// freopen("in.txt","r",stdin);
for(LL i=0;i<maxn;i++)Hash[i]=i*i+i*rand()+1;
scanf("%d%d%d",&n,&m,&k);
LL **pre=new LL *[n+5];
LL **now=new LL *[n+5];
for(int i=0;i<n+5;i++){
pre[i]=new LL[m+5];
now[i]=new LL[m+5];
}
for(int i=0;i<=n+1;i++){
for(int j=0;j<=m+1;j++){
now[i][j]=pre[i][j]=0;
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
scanf("%lld",&pre[i][j]);
pre[i][j]=Hash[pre[i][j]];
now[i][j]=0;
}
}
for(int i=0;i<k;i++){
scanf("%d%d%d%d%d",&x1,&Y1,&x2,&y2,&z);
now[x1][Y1]+=Hash[z];
now[x1][y2+1]-=Hash[z];
now[x2+1][Y1]-=Hash[z];
now[x2+1][y2+1]+=Hash[z];
}
int ans=0;
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
now[i][j]+=now[i][j-1]+now[i-1][j]-now[i-1][j-1];
ans+=now[i][j]%pre[i][j]!=0;
}
}
printf("%d\n",ans);
return 0;
}