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); }