The 2021 CCPC Guilin Onsite (Grand Prix of EDG)
题解:
https://files.cnblogs.com/files/clrs97/2021CCPCguilin.zip
Code:
A. A Hero Named Magnus
#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
using namespace std;
int main()
{
int T;
cin>>T;
while (T--)
{
long long n;
scanf("%lld",&n);
printf("%lld\n",2*(n-1)+1);
}
return 0;
}
B. A Plus B Problem
#include <bits/stdc++.h>
using namespace std;
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
int n, q;
cin >> n >> q;
vector row(2, vector<int>(n));
set<int> s;
for (int i = 0; i < 2; i += 1) {
string s;
cin >> s;
for (int j = 0; j < n; j += 1) row[i][j] = s[j] - '0';
}
for (int i = 0; i < n; i += 1) if (row[0][i] + row[1][i] != 9) s.insert(i);
for (int i = 0, r, c, d; i < q; i += 1) {
cin >> r >> c >> d;
r -= 1;
c -= 1;
s.erase(c);
auto it = s.lower_bound(c);
int p = it != s.end() and row[0][*it] + row[1][*it] >= 10;
int org = row[0][c] + row[1][c] + p;
row[r][c] = d;
int cur = row[0][c] + row[1][c] + p;
cout << cur % 10 << " ";
if (org == cur) cout << "0\n";
else if ((org < 10) ^ (cur < 10)) cout << 2 + c - (it == s.begin() ? 0 : *prev(it)) << "\n";
else cout << "2\n";
if (cur - p != 9) s.insert(c);
}
return 0;
}
C. AC Automaton
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=3e5+1e3+7,S=1833;
typedef pair<int,int> pii;
#define fs first
#define sd second
#define mp make_pair
int n,q;
vector<int>g[N];
char s[N];
struct BIT{
int c[N];
void add(int x,int v)
{
while(x<=n)
{
c[x]+=v;
x+=x&-x;
}
}
int qry(int x)
{
int ret=0;
while(x)
{
ret+=c[x];
x-=x&-x;
}
return ret;
}
}T[3];
int st[N],ed[N],fa[N];
int dc;
void dfs(int x)
{
st[x]=++dc;
for(auto v:g[x])
dfs(v);
ed[x]=dc;
}
ll ans;
int val[N];
int cp[N];
char ch[N];
int tag[N],bel[N],bid,app[N],last[N],up[N];
vector<int>h[N];
struct Edge{
int ne,to;
}edg[N];
int ct,head[N];
void build(int u,int v)
{
++ct;
edg[ct].to=v;
edg[ct].ne=head[u];
head[u]=ct;
}
int lp[N],rv[N];
int sz[N],ps[N],ord[N],pi;
void go(int x)
{
ps[x]=++pi;
ord[pi]=x;
sz[x]=1;
for(int tmp=head[x];tmp;tmp=edg[tmp].ne)
go(edg[tmp].to),sz[x]+=sz[edg[tmp].to];
}
void ss()
{
for(int x=1;x<=n;x++)
{
for(auto v:g[x])
lp[v]=tag[x]?x:lp[x];
}
for(int x=n;x>=1;x--)
{
rv[x]=0;
int sv=-1;
for(auto v:g[x])
{
rv[x]+=rv[v]>0;
if(rv[v]>0)
sv=v;
}
int cnt=rv[x];
if(tag[x])
bel[x]=++bid;
else
{
if(cnt==0)
{
if(lp[x])
{
if(!app[lp[x]])
app[lp[x]]=++bid,bel[x]=bid;
else
bel[x]=app[lp[x]];
}
else
bel[x]=0;
}
else if(cnt==1)
{
if(sv==-1)
while(1);
if(tag[sv])
bel[x]=++bid;
else
bel[x]=bel[sv];
}
else
bel[x]=++bid;
}
if(tag[x])
rv[x]++;
for(auto v:g[x])
if(bel[v]!=bel[x]&&bel[v]&&bel[x]&&!up[bel[v]])
build(bel[x],bel[v]),up[bel[v]]=bel[x];
}
pi=0;
go(bel[1]);
}
int vis[S*4][S*2+1];
int cnt[S*4],ts[S*4];
void godownadd(int pid)
{
if(!pid)
return;
for(int t=ps[pid]+1;t<=ps[pid]+sz[pid]-1;t++)
{
int x=ord[t];
ans-=cnt[x];
cnt[x]-=vis[x][-ts[x]+1+S];
ts[x]--;
}
// for(int tmp=head[pid];tmp;tmp=edg[tmp].ne)
// godownadd(edg[tmp].to);
}
void godowndel(int pid)
{
if(!pid)
return;
for(int t=ps[pid]+1;t<=ps[pid]+sz[pid]-1;t++)
{
int x=ord[t];
ts[x]++;
cnt[x]+=vis[x][-ts[x]+1+S];
ans+=cnt[x];
}
// for(int tmp=head[pid];tmp;tmp=edg[tmp].ne)
// godowndel(edg[tmp].to);
}
void goup(int pid,int v)
{
if(v==1){
while(pid){
ts[pid]++;
cnt[pid]+=vis[pid][-ts[pid]+1+S];
ans+=cnt[pid];
pid=up[pid];
}
}else{
while(pid){
ans-=cnt[pid];
cnt[pid]-=vis[pid][-ts[pid]+1+S];
ts[pid]--;
pid=up[pid];
}
}
}
void ins(int x,int v)
{
//part 1
if(s[x]=='A')
{
ans+=(T[0].qry(ed[x])-T[0].qry(st[x]))*v;
T[1].add(st[x]+1,v);
T[1].add(ed[x]+1,-v);
}
else
{
ans+=T[1].qry(st[x])*v;
T[0].add(st[x],v);
}
if(s[x]=='?')
{
if(val[x]>=-S&&val[x]<=S)
vis[bel[x]][val[x]+S]+=v;
if(val[x]+ts[bel[x]]>0)
ans+=(val[x]+ts[bel[x]])*v,cnt[bel[x]]+=v;
}
}
void chg1(int x,char ol,char nw)
{
int v=(nw!='C')-(ol!='C');
if(v==1)
godownadd(bel[x]);
else if(v==-1)
godowndel(bel[x]);
v=(nw!='A')-(ol!='A');
if(v)
goup(up[bel[x]],v);
}
/*
void ins(int x,int v)
{
//part 1
if(s[x]=='A')
{
ans+=(T[0].qry(ed[x])-T[0].qry(st[x]))*v;
T[1].add(st[x]+1,v);
T[1].add(ed[x]+1,-v);
}
else
{
ans+=T[1].qry(st[x])*v;
T[0].add(st[x],v);
}
if(s[x]=='?')
{
if(val[x]>=-S&&val[x]<=S)
vis[bel[x]][val[x]+S]+=v;
if(val[x]+ts[bel[x]]>0)
ans+=(val[x]+ts[bel[x]])*v,cnt[bel[x]]+=v;
}
if(s[x]=='?'||s[x]=='A'){
if(v==1)
godownadd(bel[x]);
// for(int tmp=head[bel[x]];tmp;tmp=edg[tmp].ne)
// godownadd(edg[tmp].to);
else
godowndel(bel[x]);
// for(int tmp=head[bel[x]];tmp;tmp=edg[tmp].ne)
// godowndel(edg[tmp].to);
}
if(s[x]=='?'||s[x]=='C')
goup(up[bel[x]],v);
}
*/
int main()
{
scanf("%d%d",&n,&q);
scanf("%s",s+1);
for(int i=2;i<=n;i++)
{
scanf("%d",&fa[i]);
g[fa[i]].push_back(i);
}
dfs(1);
for(int x=1;x<=n;x++)
{
if(s[x]=='A')
{
T[1].add(st[x]+1,1);
T[1].add(ed[x]+1,-1);
}
else
T[0].add(st[x],1);
if(s[x]=='A'||s[x]=='?')
{
T[2].add(st[x]+1,1);
T[2].add(ed[x]+1,-1);
}
}
for(int i=1;i<=n;i++)
if(s[i]=='A')
ans+=T[0].qry(ed[i])-T[0].qry(st[i]-1);
for(int i=1;i<=n;i++)
{
val[i]=T[0].qry(ed[i])-T[0].qry(st[i])-T[2].qry(st[i]);
if(val[i]>0&&s[i]=='?')
ans+=val[i];
}
for(int i=1;i<=q;i++)
scanf("%d%s",&cp[i],ch+i);
for(int i=1;i<=q;i+=S)
{
int j=min(i+S-1,q);
for(int k=i;k<=j;k++)if(k==i||s[cp[k]]!=ch[k])
tag[cp[k]]=1,app[cp[k]]=0;
for(int k=0;k<=bid;k++)
head[k]=0,up[k]=0;
ct=0;
bid=0;
// dfs(1,0);
ss();
for(int t=0;t<=bid;t++)
ts[t]=0,cnt[t]=0;
for(int k=1;k<=n;k++)
{
if(s[k]=='?')
{
if(val[k]>=-S&&val[k]<=S)
vis[bel[k]][val[k]+S]++;
if(val[k]>0)
cnt[bel[k]]++;
}
}
for(int k=i;k<=j;k++)
{
int x=cp[k];
char c=ch[k];
if(s[x]!=c)
{
chg1(x,s[x],c);
ins(x,-1);
s[x]=c;
ins(x,1);
}
printf("%lld\n",ans);
}
for(int k=1;k<=n;k++)
{
if(val[k]>=-S&&val[k]<=S)
vis[bel[k]][val[k]+S]=0;
if(bel[k])
val[k]+=ts[bel[k]];
bel[k]=0;
}
for(int k=i;k<=j;k++)
tag[cp[k]]=0;
}
}
D. Assumption is All You Need
#include<bits/stdc++.h>
#define rep(i,n) for(int i=1;i<=n;++i)
#define trav(a,x) for(auto&a:x)
#define all(x) begin(x),end(x)
#define sz(x) (int)(x).size()
#define pb push_back
#define mp make_pair
#define x0 fuckhel
#define y0 fuckoscar
#define x1 fucksub
#define y1 fuckzzy
#define st first
#define nd second
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pr;
typedef vector<int> vi;
const int N=2050,mod=1e9+7;
int a[N],b[N],Pa[N],Pb[N],T,n,top;
pr s[N*N/2];
bool sol(){
top=0;
rep(i,n)
if(Pa[i]<Pb[i])
return 0;
else{
for(int j=i+1;j<=n;++j)
if(Pb[i]<=Pa[j]&&Pa[j]<Pa[i]){
s[++top]=mp(Pa[j],Pa[i]);
swap(Pa[i],Pa[j]);
}
}
return 1;
}
int main(){
for(scanf("%d",&T);T--;){
scanf("%d",&n);
rep(i,n)scanf("%d",a+i),Pa[a[i]]=i;
rep(i,n)scanf("%d",b+i),Pb[b[i]]=i;
if(sol()){
printf("%d\n",top);
rep(i,top)printf("%d %d\n",s[i].st,s[i].nd);
}else puts("-1");
}
return 0;
}
E. Buy and Delete
#include<cstdio>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
typedef pair<int,int>P;
const int N=2005,M=5005,inf=~0U>>1;
int n,m,c,mi,ans,S,i,j,x,y,z,g[N],u[M],v[M],w[M],nxt[M],d[N];
priority_queue<P,vector<P>,greater<P> >q;
inline void up(int&a,int b){a>b?(a=b):0;}
inline void ext(int x,int y){
if(d[x]<=y)return;
q.push(P(d[x]=y,x));
}
int main(){
scanf("%d%d%d",&n,&m,&c);
mi=ans=inf;
for(i=1;i<=m;i++){
scanf("%d%d%d",&x,&y,&z);
up(mi,z);
u[i]=x;
v[i]=y;
w[i]=z;
nxt[i]=g[x];
g[x]=i;
}
for(S=1;S<=n;S++){
for(i=1;i<=n;i++)d[i]=inf;
ext(S,0);
while(!q.empty()){
P t=q.top();q.pop();
if(d[t.second]<t.first)continue;
for(i=g[t.second];i;i=nxt[i])ext(v[i],t.first+w[i]);
}
for(i=1;i<=m;i++)if(d[u[i]]<inf&&v[i]==S)up(ans,d[u[i]]+w[i]);
}
if(c<mi)puts("0");
else if(c<ans)puts("1");
else puts("2");
}
F. Illuminations II
#include <bits/stdc++.h>
using namespace std;
using LL = long long;
struct P{
LL x, y;
P operator - (const P& p) const {return {x - p.x, y - p.y};}
LL cross(const P& p) const {return x * p.y - y * p.x;}
double norm() const {return hypot(x, y);}
};
int main() {
cin.tie(nullptr)->sync_with_stdio(false);
cout << fixed << setprecision(20);
int n, m;
cin >> n >> m;
vector<P> p(n), q(m);
for (auto& [x, y] : p) cin >> x >> y;
for (auto& [x, y] : q) cin >> x >> y;
vector<double> s(n), ss(n);
for (int i = 0; i < n; i += 1) {
ss[i] = s[i] = (p[i] - p[(i + 1) % n]).norm();
if (i) ss[i] += ss[i - 1];
}
auto intersection = [&](const P& A, const P& B, const P& C, const P& D) -> P {
LL x = (C - A).cross(D - C), y = (B - A).cross(D - C);
if (y < 0) {
x = -x;
y = -y;
}
return {x, y};
};
auto intersect = [&](const P& A, const P& B, int i) -> optional<double> {
const P &C = p[i], &D = p[(i + 1) % n];
if ((B - A).cross(D - C) == 0) return nullopt;
if(intersection(A, B, C, D).x < 0) return nullopt;
auto [x, y] = intersection(C, D, A, B);
if (x >= y or x < 0) return nullopt;
return (i ? ss[i - 1] : 0) + s[i] / y * x;
};
int f = 0, t = 0;
double ans = 0;
for (int i = 0; i < m; i += 1) {
const P &A = q[i], &B = q[(i + 1) % m];
while (not intersect(B, A, f).has_value()) f = (f + 1) % n;
while (not intersect(A, B, t).has_value()) t = (t + 1) % n;
double df = intersect(B, A, f).value(), dt = intersect(A, B, t).value();
if (dt < df) dt += ss.back();
ans += (A - B).norm() * (dt - df);
}
cout << ans / ss.back();
return 0;
}
G. Occupy the Cities
#include <bits/stdc++.h>
using namespace std;
int T;
char s[1000010];
int main() {
scanf("%d",&T);
while(T--) {
int n;
scanf("%d",&n);
scanf("%s",s + 1);
vector<int> idx;
for (int i = 1; i <= n; i++) {
if (s[i] == '1') idx.push_back(i);
}
assert(idx.size());
if (idx.size() == n) {
puts("0");
continue;
}
int max_gap = max(idx[0] - 1, n - idx[idx.size() - 1]);
for (int i = 1; i < idx.size(); i++) {
max_gap = max(max_gap, (idx[i] - idx[i - 1] - 1) / 2);
}
auto check = [&](int x) {
int R = 0;
for (auto &t : idx) {
if (R < t - x - 1) return false;
if (R == t - x - 1) {
R = max(R, t + x - 1);
} else {
R = max(R, t + x);
}
}
return R >= n;
};
for (int i = max_gap; ; i++) {
if (check(i)) {
printf("%d\n",i);
break;
}
}
}
}
H. Popcount Words
#include<cstdio>
typedef long long ll;
const int N=100005,M=100005,LEN=500005,K=30;
int n,m,i,j,k,x,y,l[N],r[N],L[K],R[K],at[M];
int tot,son[LEN][2],fail[LEN],q[LEN];
ll ans[LEN],f[K+1][LEN][2],tmp;
int g[K+1][LEN][2];
inline int ins(){
static char s[LEN];
scanf("%s",s);
int x=0;
for(int i=0;s[i];i++){
int w=s[i]-'0';
if(!son[x][w])son[x][w]=++tot;
x=son[x][w];
}
return x;
}
void make(){
int h=1,t=0,i,j,x;
fail[0]=-1;
for(i=0;i<2;i++)if(son[0][i])q[++t]=son[0][i];
while(h<=t){
x=q[h++];
for(i=0;i<2;i++){
if(son[x][i]){
fail[son[x][i]]=son[fail[x]][i];
q[++t]=son[x][i];
}else son[x][i]=son[fail[x]][i];
}
}
}
inline void decode(int x,int*f){
for(int i=K-1;~i;i--){
f[i]=x&1;
x>>=1;
}
}
int dfs(int x,int s,int el,int er,int o){
if((!el&&!er)||(o==K)){
f[o][x][s]++;
return g[o][x][s];
}
for(int i=0;i<2;i++){
int nel=el,ner=er;
if(el){
if(i<L[o])continue;
if(i>L[o])nel=0;
}
if(er){
if(i>R[o])continue;
if(i<R[o])ner=0;
}
x=dfs(x,s^i,nel,ner,o+1);
}
return x;
}
int main(){
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)scanf("%d%d",&l[i],&r[i]);
for(i=1;i<=m;i++)at[i]=ins();
make();
for(i=0;i<=tot;i++)for(j=0;j<2;j++)g[K][i][j]=son[i][j];
for(i=K-1;i;i--)for(j=0;j<=tot;j++)for(k=0;k<2;k++){
x=j;
for(y=0;y<2;y++)x=g[i+1][x][k^y];
g[i][j][k]=x;
}
x=0;
for(i=1;i<=n;i++){
decode(l[i],L);
decode(r[i],R);
x=dfs(x,0,1,1,0);
}
for(i=1;i<K;i++)for(j=0;j<=tot;j++)for(k=0;k<2;k++){
tmp=f[i][j][k];
if(!tmp)continue;
for(x=j,y=0;y<2;y++){
f[i+1][x][k^y]+=tmp;
x=g[i+1][x][k^y];
}
}
for(i=0;i<=tot;i++)for(j=0;j<2;j++)ans[g[K][i][j]]+=f[K][i][j];
for(i=tot;i;i--)ans[fail[q[i]]]+=ans[q[i]];
for(i=1;i<=m;i++)printf("%lld\n",ans[at[i]]);
}
I. PTSD
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
int n;
char s[1000100];
int main() {
int T;
scanf("%d",&T);
while(T--) {
scanf("%d", &n);
scanf("%s", s + 1);
LL ans = 0;
int cnt = 0;
for (int i = n; i >= 1; i--) {
if (s[i] == '1' && cnt > 0) {
cnt--;
ans += i;
} else {
cnt++;
}
}
printf("%lld\n",ans);
}
}
J. Suffix Automaton
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<queue>
#include<set>
#include<unordered_map>
#include<unordered_set>
#include<map>
#include<cassert>
#include<string>
using namespace std;
#define pb push_back
#define mp make_pair
#define rep(i,n) for(int i=1;i<=n;i++)
typedef long long LL;
namespace SuffixTree
{
const int inf=1<<25,S=27,N=1000010;
int root,last,pos,need,remain,acnode,ace,aclen;
struct node{int st,en,lk,son[S];int len(){ return min(en,pos+1)-st;}}tree[N<<1];
int n;char text[N],tmp[N];
int new_node(int st,int en=inf)
{
node nd;
nd.st=st;nd.en=en;
for(int i=nd.lk=0;i<S;i++)nd.son[i]=0;
tree[++last]=nd;
return last;
}
char acedge(){ return text[ace];}
void addedge(int node)
{
if (need)tree[need].lk=node;
need=node;
}
bool down(int node)
{
if (aclen>=tree[node].len()){
ace+=tree[node].len(),aclen-=tree[node].len(),acnode=node;
return 1;
}
return 0;
}
void init()
{
need=last=remain=ace=aclen=0;
root=acnode=new_node(pos=-1,-1);
}
void extend(char c)
{
text[++pos]=c;need=0;remain++;
while (remain)
{
if (!aclen)ace=pos;
if (!tree[acnode].son[acedge()])
{
tree[acnode].son[acedge()]=new_node(pos);
addedge(acnode);
}else
{
int nxt=tree[acnode].son[acedge()];
if (down(nxt))continue;
if (text[tree[nxt].st+aclen]==c){aclen++;addedge(acnode);break;}
int split=new_node(tree[nxt].st,tree[nxt].st+aclen);
tree[acnode].son[acedge()]=split;
tree[split].son[c]=new_node(pos);
tree[nxt].st+=aclen;
tree[split].son[text[tree[nxt].st]]=nxt;
addedge(split);
}
remain--;
if (acnode==root&&aclen)aclen--,ace=pos-remain+1;
else acnode=tree[acnode].lk?tree[acnode].lk:root;
}
}
int tot;
void dfs(int x,int dep,vector<int>g[],int ansl[])
{
if(x!=root)
{
int l=tree[x].st-dep+1;ansl[++tot]=l;
g[dep+1].pb(tot);
dep+=tree[x].len();
g[dep+1].pb(-tot);
}
for(int i=0;i<S;i++)if(tree[x].son[i])dfs(tree[x].son[i],dep,g,ansl);
}
void main(int& _n,int&m,vector<int>g[],int ansl[])
{
init();
scanf("%s",tmp+1);
n=strlen(tmp+1);
for(int i=1;i<=n;i++)extend(tmp[i]-'a'); extend(26);
pos--;
dfs(root,0,g,ansl);
_n=n;m=tot;
}
}
const int N=1000010;
vector<int>g[N];
vector<pair<int,int>>Q[N];
pair<int,int>ans[N];
int n,m,q,tree[N<<3],ansl[N<<1];
LL sum[N];
void modify(int p,int le,int ri,int x,int y)
{
tree[p]+=y;
if(le==ri)return;
int mid=(le+ri)>>1;
if(x<=mid)modify(p<<1,le,mid,x,y);
else modify(p<<1|1,mid+1,ri,x,y);
}
int get(int p,int le,int ri,int k)
{
if(le==ri)return le;
int mid=(le+ri)>>1;
if(tree[p<<1]>=k)return get(p<<1,le,mid,k);
else return get(p<<1|1,mid+1,ri,k-tree[p<<1]);
}
int main()
{
SuffixTree::main(n,m,g,ansl);
rep(i,n)for(auto j:g[i])sum[i]+=j>0?1:-1;
rep(i,n)sum[i]+=sum[i-1];
rep(i,n)sum[i]+=sum[i-1];
scanf("%d",&q);
rep(i,q)
{
LL k;scanf("%lld",&k);
int len=lower_bound(sum+1,sum+n+1,k)-sum;
if(len>n)ans[i]=mp(-1,-1);
else Q[len].pb(mp(k-sum[len-1],i));
}
rep(i,n)
{
for(auto j:g[i])modify(1,1,m,abs(j),j>0?1:-1);
for(auto j:Q[i])
{
int l=ansl[get(1,1,m,j.first)];
ans[j.second]=mp(l,l+i-1);
}
}
rep(i,q)printf("%d %d\n",ans[i].first,ans[i].second);
return 0;
}
K. Tax
#include<cstdio>
const int N=55,M=N*N,inf=~0U>>1;
int n,m,i,j,x,y,z,w[M],g[N][N],h,t,q[N],d[N];
int pool[N][N],cnt[N],ans[N],vis[M],cur;
void dfs(int dis,int x){
if(ans[x]>cur)ans[x]=cur;
dis++;
for(int i=1;;i++){
int y=pool[dis][i];
if(!y)break;
int z=g[x][y];
if(!z)continue;
vis[z]++;
cur+=vis[z]*w[z];
dfs(dis,y);
cur-=vis[z]*w[z];
vis[z]--;
}
}
int main(){
scanf("%d%d",&n,&m);
for(i=1;i<=m;i++)scanf("%d",&w[i]);
while(m--){
scanf("%d%d%d",&x,&y,&z);
g[x][y]=g[y][x]=z;
}
q[h=t=1]=1;
d[1]=1;
while(h<=t){
x=q[h++];
for(i=1;i<=n;i++)if(g[x][i]&&!d[i]){
d[i]=d[x]+1;
q[++t]=i;
}
}
for(i=1;i<=n;i++)pool[d[i]][++cnt[d[i]]]=i;
for(i=1;i<=n;i++)ans[i]=inf;
dfs(1,1);
for(i=2;i<=n;i++)printf("%d\n",ans[i]);
}
L. Wiring Engineering
#include<cstdio>
const int N=505,M=300005,inf=1000000000;
int n,m,i,j,a[N],b[N],w[N][N],q[M],pool[M];
int pre[N][N],suf[N][N],g[N][N],h[N][N];
struct E{int al,ar,bl,br,ans;}e[M];
inline void umin(int&a,int b){a>b?(a=b):0;}
inline void up(int&a,int b){a<b?(a=b):0;}
inline void init(int A,int B,int C,int D,int f[][N]){
int i,j;
A--,B++,C--,D++;
for(i=A;i<=B;i++)for(j=C;j<=D;j++)f[i][j]=g[i][j]=h[i][j]=-inf;
}
inline void back(int A,int B,int C,int D,int f[][N]){
int i,j,k,t;
for(i=B;i>=A;i--)for(j=D;j>=C;j--){
k=-inf;
up(k,f[i+1][j]);
up(k,g[i][j+1]);
t=w[i][j]-b[j];
up(k,g[i][j+1]+t);
up(k,h[i+1][j]+t);
up(g[i][j],k);
k=-inf;
up(k,f[i][j+1]);
up(k,h[i+1][j]);
t=w[i][j]-a[i];
up(k,g[i][j+1]+t);
up(k,h[i+1][j]+t);
up(h[i][j],k);
k=-inf;
up(k,f[i+1][j]);
up(k,f[i][j+1]);
up(k,g[i][j]-a[i]);
up(k,h[i][j]-b[j]);
up(f[i][j],k);
}
}
inline void go(int A,int B,int C,int D,int f[][N]){
int i,j,k;
for(i=A;i<=B;i++)for(j=C;j<=D;j++){
k=f[i][j];
up(f[i+1][j],k);
up(f[i][j+1],k);
up(g[i][j],k-a[i]);
up(h[i][j],k-b[j]);
k=g[i][j];
up(f[i+1][j],k);
up(g[i][j+1],k);
k+=w[i][j]-b[j];
up(g[i][j+1],k);
up(h[i+1][j],k);
k=h[i][j];
up(f[i][j+1],k);
up(h[i+1][j],k);
k+=w[i][j]-a[i];
up(g[i][j+1],k);
up(h[i+1][j],k);
}
}
void solvecol(int A,int B,int C,int D,int L,int R);
void solverow(int A,int B,int C,int D,int L,int R){
if(A>B||C>D||L>R)return;
int m=(A+B)>>1,i,j,k,o,cp=0,xl,xr,yl,yr;
xl=yl=n+1,xr=yr=0;
for(i=L;i<=R;i++){
o=q[i];
if(e[o].al<=m&&e[o].ar>=m){
umin(xl,e[o].al);
up(xr,e[o].ar);
umin(yl,e[o].bl);
up(yr,e[o].br);
pool[++cp]=o;
}
}
for(i=yl;i<=yr;i++){
init(xl,m,yl,i,pre);
h[m][i]=0;
back(xl,m,yl,i,pre);
init(m,xr,i,yr,suf);
h[m][i]=0;
go(m,xr,i,yr,suf);
for(k=1;k<=cp;k++){
o=pool[k];
if(e[o].bl<=i&&e[o].br>=i)up(e[o].ans,pre[e[o].al][e[o].bl]+suf[e[o].ar][e[o].br]);
}
}
int _L=L-1,_R=R+1;
for(i=L;i<=R;i++){
o=q[i];
if(e[o].ar<m)pool[++_L]=o;
if(e[o].al>m)pool[--_R]=o;
}
for(i=L;i<=R;i++)q[i]=pool[i];
solvecol(A,m-1,C,D,L,_L);
solvecol(m+1,B,C,D,_R,R);
}
void solvecol(int A,int B,int C,int D,int L,int R){
if(A>B||C>D||L>R)return;
int m=(C+D)>>1,i,j,k,o,cp=0,xl,xr,yl,yr;
xl=yl=n+1,xr=yr=0;
for(i=L;i<=R;i++){
o=q[i];
if(e[o].bl<=m&&e[o].br>=m){
umin(xl,e[o].al);
up(xr,e[o].ar);
umin(yl,e[o].bl);
up(yr,e[o].br);
pool[++cp]=o;
}
}
for(i=xl;i<=xr;i++){
init(xl,i,yl,m,pre);
g[i][m]=0;
back(xl,i,yl,m,pre);
init(i,xr,m,yr,suf);
g[i][m]=0;
go(i,xr,m,yr,suf);
for(k=1;k<=cp;k++){
o=pool[k];
if(e[o].al<=i&&e[o].ar>=i)up(e[o].ans,pre[e[o].al][e[o].bl]+suf[e[o].ar][e[o].br]);
}
}
int _L=L-1,_R=R+1;
for(i=L;i<=R;i++){
o=q[i];
if(e[o].br<m)pool[++_L]=o;
if(e[o].bl>m)pool[--_R]=o;
}
for(i=L;i<=R;i++)q[i]=pool[i];
solverow(A,B,C,m-1,L,_L);
solverow(A,B,m+1,D,_R,R);
}
int main(){
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)scanf("%d",&a[i]);
for(i=1;i<=n;i++)scanf("%d",&b[i]);
for(i=1;i<=n;i++)for(j=1;j<=n;j++)scanf("%d",&w[i][j]);
for(i=1;i<=m;i++){
scanf("%d%d%d%d",&e[i].al,&e[i].ar,&e[i].bl,&e[i].br);
e[i].ar++,e[i].br++;
q[i]=i;
}
solverow(1,n+1,1,n+1,1,m);
for(i=1;i<=m;i++)printf("%d\n",e[i].ans);
}

浙公网安备 33010602011771号