传送门
- 关于一类 \(O(\frac{nV}{\omega})\) 计算带偏移量的 \(\sum\limits_{i=l}^r|a_{dlt_1+i}-b_{dlt_2+i}|\) 的方法:
考虑将一个 \(a-b\) 的贡献拆开,在每个 \(c\in[b, a]\) 都统计一次
一个做法是把所有数分为 \(<c\) 和 \(\geqslant c\) 的两部分,一个记作 0,另一个记作 1
那么我们实际上是要求 \(a, b\) 各一个区间的异或的 \(\tt popcount\)
这个做法还可以优化到 \(O(V(\frac{n^2}{B}+qB))\),方法直接粘题解了

点击查看代码
%:pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 101010
#define ll long long
//#define int long long
char buf[1<<21], *p1=buf, *p2=buf;
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
}
int n, q;
int a[N], b[N], maxc;
// namespace force{
// void solve() {
// for (int i=1,p1,p2,x,ans; i<=q; ++i) {
// p1=read(); p2=read(); x=read(); ans=0;
// for (int j=1; j<=x; ++j) ans+=abs(a[p1+j-1]-b[p2+j-1]);
// printf("%d\n", ans);
// }
// }
// }
// namespace task1{
// bitset<N> as[6], bs[6];
// void solve() {
// for (int c=2; c<=5; ++c) {
// for (int i=0; i<n; ++i) if (c<=a[i]) as[c][i]=1;
// for (int i=0; i<n; ++i) if (c<=b[i]) bs[c][i]=1;
// }
// for (int i=1,p1,p2,x,ans; i<=q; ++i) {
// p1=read()-1; p2=read()-1; x=read(); ans=0;
// for (int c=2; c<=5; ++c) {
// ans+=((as[c]>>p1)^(bs[c]>>p2)).count();
// ans-=((as[c]>>p1+x)^(bs[c]>>p2+x)).count();
// }
// printf("%d\n", ans);
// }
// }
// }
// namespace task2{
// const int w=128;
// bitset<N> sa[6], sb[6], tem;
// bitset<w> aper[6][w][N/w], bper[6][N/w];
// int cnt[6][w][N/w][N/w], sum[6][w][N/w][N/w];
// void solve() {
// // cout<<double(sizeof(aper)+sizeof(bper)+sizeof(cnt)*2)/1000/1000<<endl;
// for (int c=2; c<=5; ++c,tem.reset()) {
// for (int i=0; i<n; ++i) if (c<=a[i]) sa[c][i]=tem[i]=1;
// for (int dlt=0; dlt<w; ++dlt,tem<<=1) {
// tem=sa[c]<<dlt;
// // cout<<"tem: "<<tem<<endl;
// for (int l=0,r,id=0; l<n+w; l=r+1,++id) {
// r=l+w-1;
// // cout<<"lr: "<<l<<' '<<r<<endl;
// for (int j=l; j<=r; ++j) aper[c][dlt][id][j-l]=tem[j];
// // cout<<"aper: "<<aper[c][dlt][id]<<endl;
// }
// }
// }
// for (int c=2; c<=5; ++c) {
// for (int i=0; i<n; ++i) if (c<=b[i]) sb[c][i]=1;
// for (int l=0,r,id=0; l<n; l=r+1,++id) {
// r=l+w-1;
// // cout<<"id: "<<l<<' '<<r<<' '<<id<<endl;
// for (int j=l; j<=r; ++j) bper[c][id][j-l]=sb[c][j];
// }
// }
// for (int c=2; c<=5; ++c)
// for (int dlt=0; dlt<w; ++dlt)
// for (int i=0; i<=(n+w)/w; ++i)
// for (int j=0; j<=n/w; ++j)
// cnt[c][dlt][i][j]=(aper[c][dlt][i]^bper[c][j]).count();
// for (int c=2; c<=5; ++c)
// for (int dlt=0; dlt<w; ++dlt)
// for (int i=0; i<=(n+w)/w; ++i)
// for (int j=0; j<=n/w; ++j)
// sum[c][dlt][i][j]=(i&&j?sum[c][dlt][i-1][j-1]:0)+cnt[c][dlt][i][j];
// for (int i=1,p1,p2,x,ans; i<=q; ++i) {
// p1=read()-1; p2=read()-1; x=read(); ans=0;
// // if (x<w) {for (int j=0; j<x; ++j) ans+=abs(a[p1+j]-b[p2+j]); printf("force: %d\n", ans); continue;}
// if (x<w) {for (int j=0; j<x; ++j) ans+=abs(a[p1+j]-b[p2+j]); printf("%d\n", ans); continue;}
// int ida=p1%w, idb=p2%w, dlt;
// // cout<<"p: "<<p1<<' '<<p2<<endl;
// // cout<<"x: "<<x<<endl;
// // cout<<"rest: "<<ida<<' '<<idb<<endl;
// if (ida<=idb) dlt=idb-ida;
// else dlt=w+idb-ida;
// // cout<<"dlt: "<<dlt<<endl;
// for (int c=2; c<=5; ++c) {
// // for (int j=0; j<x; ++j) ans+=sa[c][p1+j]^sb[c][p2+j]; continue;
// for (int j=0; j<w-idb; ++j) ans+=sa[c][p1+j]^sb[c][p2+j];
// // cout<<"w-idb: "<<w-idb<<endl;
// int pos1=(p1+dlt)/w+1, pos2=p2/w+1;
// // cout<<"pos: "<<pos1<<' '<<pos2<<endl;
// int lim=(x-w+idb)/w;
// // cout<<"lim: "<<(x-w+idb)/w<<endl;
// // for (int j=1; j<=(x-w+idb)/w; ++j,++pos1,++pos2) {
// // // cout<<"j: "<<j<<endl;
// // // bitset<N> tem=sa[c]<<dlt; int val=0;
// // // for (int k=0; k<w; ++k) ans+=tem[w*pos1+k]^sb[c][w*pos2+k], val+=tem[w*pos1+k]^sb[c][w*pos2+k];
// // // for (int k=w-1; ~k; --k) cout<<tem[w*pos1+k]; cout<<' ';
// // // for (int k=w-1; ~k; --k) cout<<sb[c][w*pos2+k]; cout<<endl;
// // // cout<<"val: "<<val<<endl;
// // ans+=cnt[c][dlt][pos1][pos2]; //, cout<<cnt[c][dlt][pos1][pos2]<<endl;
// // // cout<<"cnt: "<<cnt[c][dlt][pos1][pos2]<<endl;
// // // cout<<aper[c][dlt][pos1]<<' '<<bper[c][pos2]<<endl;
// // // ans+=(aper[c][dlt][pos1]^bper[c][pos2]).count();
// // }
// ans+=sum[c][dlt][pos1+lim-1][pos2+lim-1]-(pos1&&pos2?sum[c][dlt][pos1-1][pos2-1]:0);
// // cout<<"now: "<<w*((x-w+idb)/w)+w-idb<<endl;
// for (int now=w*((x-w+idb)/w)+w-idb; now<x; ++now) ans+=sa[c][p1+now]^sb[c][p2+now]; //, cout<<now<<' '<<(int)(sa[c][p1+now]^sb[c][p2+now])<<endl;
// }
// printf("%d\n", ans);
// }
// }
// }
namespace task{
const int w=170, len=300;
bitset<N> sa, sb, tem;
int p1[N*10], p2[N*10], x[N*10];
bitset<w> aper[w][N/w+10], bper[N/w+10];
int cnt[w][N/w+10][N/w+10], sum[w][N/w+10][N/w+10], ans[N*10];
void solve() {
// cout<<double(sizeof(aper)+sizeof(bper)+sizeof(cnt)*2)/1000/1000<<endl; exit(0);
for (int i=1; i<=q; ++i) {
p1[i]=read()-1, p2[i]=read()-1, x[i]=read();
if (x[i]<len) {for (int j=0; j<x[i]; ++j) ans[i]+=abs(a[p1[i]+j]-b[p2[i]+j]);}
}
for (int c=2; c<=maxc; ++c) {
sa.reset(), sb.reset(), tem.reset();
for (int i=0; i<n; ++i) if (c<=a[i]) sa[i]=tem[i]=1;
for (int dlt=0; dlt<w; ++dlt,tem<<=1) {
for (int l=0,r,id=0; l<n+w; l=r+1,++id) {
r=l+w-1;
for (int j=l; j<=r; ++j) aper[dlt][id][j-l]=tem[j];
}
}
for (int i=0; i<n; ++i) if (c<=b[i]) sb[i]=1;
for (int l=0,r,id=0; l<n; l=r+1,++id) {
r=l+w-1;
for (int j=l; j<=r; ++j) bper[id][j-l]=sb[j];
}
for (int dlt=0; dlt<w; ++dlt)
for (int i=0; i<=(n+w)/w; ++i)
for (int j=0; j<=n/w; ++j)
cnt[dlt][i][j]=(aper[dlt][i]^bper[j]).count();
for (int dlt=0; dlt<w; ++dlt)
for (int i=0; i<=(n+w)/w; ++i)
for (int j=0; j<=n/w; ++j)
sum[dlt][i][j]=(i&&j?sum[dlt][i-1][j-1]:0)+cnt[dlt][i][j];
for (int i=1,p1,p2,x,ans; i<=q; ++i) {
p1=task::p1[i]; p2=task::p2[i]; x=task::x[i]; ans=0;
if (x<len) continue;
int ida=p1%w, idb=p2%w, dlt;
if (ida<=idb) dlt=idb-ida;
else dlt=w+idb-ida;
for (int j=0; j<w-idb; ++j) ans+=sa[p1+j]^sb[p2+j];
int pos1=(p1+dlt)/w+1, pos2=p2/w+1;
int lim=(x-w+idb)/w;
ans+=sum[dlt][pos1+lim-1][pos2+lim-1]-(pos1&&pos2?sum[dlt][pos1-1][pos2-1]:0);
for (int now=w*((x-w+idb)/w)+w-idb; now<x; ++now) ans+=sa[p1+now]^sb[p2+now];
task::ans[i]+=ans;
}
}
for (int i=1; i<=q; ++i) printf("%d\n", ans[i]);
}
}
signed main()
{
freopen("dist.in", "r", stdin);
freopen("dist.out", "w", stdout);
n=read(); q=read();
for (int i=0; i<n; ++i) maxc=max(maxc, a[i]=read());
for (int i=0; i<n; ++i) maxc=max(maxc, b[i]=read());
// force::solve();
// task1::solve();
task::solve();
return 0;
}