Calzonification
Undead2008 · · 题解
这个生成方式不好刻画,考虑打表观察答案网格的性质。
打表可以发现对于大部分的
证明一下。考虑对一个
所以
所以我们暴力做前三行和前三列,之后的格子颜色都可以推出,查询时是一个等差序列求和,分讨一下即可。
#include"bits/stdc++.h"
using namespace std;
#define L long long
const int maxN = 200010;
const int B = 3;
int n,q,a[B+2][maxN],b[maxN][B+2];
int Mex[2][2];
inline int Geta(int Xl,int Yl,int Xr,int Yr){
return a[Xr][Yr]-a[Xl-1][Yr]-a[Xr][Yl-1]+a[Xl-1][Yl-1];
}
inline int Getb(int Xl,int Yl,int Xr,int Yr){
return b[Xr][Yr]-b[Xl-1][Yr]-b[Xr][Yl-1]+b[Xl-1][Yl-1];
}
int Id[maxN<<1],Idx;
L Su[maxN<<1],Sl[maxN<<1],Sr[maxN<<1];
inline L Cl(int l,int r){
return (Sl[r]-Sl[l-1])-(Su[r]-Su[l-1])*(l-1);
}
inline L Cr(int l,int r){
return (Sr[r]-Sr[l-1])-(Su[r]-Su[l-1])*(Idx-r);
}
inline int Origin(int X,int Y){
int Dl=min(X-B,Y-B);
X-=Dl,Y-=Dl;
if(Y==B)return n-X+1;
return n-B+1+Y-B;
}
inline L Solve(int Xl,int Yl,int Xr,int Yr){
int Lb=Origin(Xr,Yl),Rb=Origin(Xl,Yr),Ln=min(Xr-Xl+1,Yr-Yl+1);
return Cl(Lb,Lb+Ln-1)+(Su[Rb-Ln+1]-Su[Lb+Ln-1])*Ln+Cr(Rb-Ln+2,Rb);
}
vector<L> mosaic(vector<int> Xo,vector<int> Yo,vector<int> To,vector<int> Bo,vector<int> Lo,vector<int> Ro){
n=Xo.size(),q=To.size();
Mex[0][0]=1;
vector<L>Ans;
for(int i=1;i<=n;i++)a[1][i]=Xo[i-1];
for(int j=1;j<=min(B,n);j++)a[j][1]=Yo[j-1];
for(int j=B+1;j<=n;j++)b[j][1]=Yo[j-1];
for(int i=2;i<=B;i++)
for(int j=2;j<=n;j++)
a[i][j]=Mex[a[i][j-1]][a[i-1][j]];
for(int i=B+1;i<=n;i++)
for(int j=2;j<=B;j++)
b[i][j]=Mex[b[i][j-1]][(i==B+1?a[i-1][j]:b[i-1][j])];
for(int j=n;j>B;j--)Su[++Idx]=b[j][B];
for(int j=B;j<=n;j++)Su[++Idx]=a[B][j];
for(int i=1;i<=Idx;i++)Sl[i]=Sl[i-1]+i*Su[i];
for(int i=1;i<=Idx;i++)Sr[i]=Sr[i-1]+(Idx-i+1)*Su[i];
for(int i=1;i<=Idx;i++)Su[i]=Su[i-1]+Su[i];
for(int i=1;i<=B;i++)
for(int j=1;j<=n;j++)
a[i][j]=a[i][j]+a[i-1][j]+a[i][j-1]-a[i-1][j-1];
for(int i=B+1;i<=n;i++)
for(int j=1;j<=B;j++)
b[i][j]=b[i][j]+b[i-1][j]+b[i][j-1]-b[i-1][j-1];
for(int i=1,Xl,Yl,Xr,Yr;i<=q;i++){
Xl=To[i-1]+1,Yl=Lo[i-1]+1,Xr=Bo[i-1]+1,Yr=Ro[i-1]+1;
if(Xr<=B)Ans.push_back(Geta(Xl,Yl,Xr,Yr));
else if(Xl>B&&Yr<=B)Ans.push_back(Getb(Xl,Yl,Xr,Yr));
else if(Yr<=B)Ans.push_back(Getb(B+1,Yl,Xr,Yr)+Geta(Xl,Yl,B,Yr));
else{
int A=0;
if(Xl<=B)A+=Geta(Xl,Yl,B,Yr),Xl=B+1;
if(Yl<=B)A+=Getb(Xl,Yl,Xr,B),Yl=B+1;
Ans.push_back(A+Solve(Xl,Yl,Xr,Yr));
}
}
return Ans;
}
主函数部分是直接从题目附件里贺的:
#ifndef ONLINE_JUDGE
int main() {
int N;
assert(1 == scanf("%d", &N));
std::vector<int> Xo(N), Yo(N);
for (int i = 0; i < N; i++)
assert(1 == scanf("%d", &Xo[i]));
for (int i = 0; i < N; i++)
assert(1 == scanf("%d", &Yo[i]));
int Q;
assert(1 == scanf("%d", &Q));
std::vector<int> To(Q), Bo(Q), Lo(Q), Ro(Q);
for (int k = 0; k < Q; k++)
assert(4 == scanf("%d%d%d%d", &To[k], &Bo[k], &Lo[k], &Ro[k]));
fclose(stdin);
std::vector<long long> Co = mosaic(Xo, Yo, To, Bo, Lo, Ro);
int S = (int)Co.size();
for (int k = 0; k < S; k++)
printf("%lld\n", Co[k]);
fclose(stdout);
return 0;
}
#endif