先不管旋转操作,只考虑增加亮度这个操作。显然这个玩意的影响是相对于$x,y$固定的,所以可以枚举增加的亮度然后O(1)算出来。为了方便我们把这个操作换种方法表示,只让一个手环改变$[-m,m]$中的一个亮度$k$。这样把$sumlimits_{i=1}^n(x_i-y_i+k)^2$拆完以后发现只有$sumlimits_{i=1}^n 2x_iy_i$这个玩意跟$x,y$的顺序有关,于是先扫一遍把其他的求出来
然后考虑旋转的操作,环上问题有个很经典的操作:断环为链。注意到这里是两个多项式的同一项向答案的同一项做贡献,相当于差值一定,于是就是套路的把一个多项式反过来,然后卷就完事了
1 #include<cmath> 2 #include<cstdio> 3 #include<cctype> 4 #include<cstring> 5 #include<algorithm> 6 using namespace std; 7 const int N=400005,M=30; 8 const double pai=acos(-1); 9 struct cpx 10 { 11 double x,y; 12 }a[N],b[N]; 13 cpx operator + (cpx a,cpx b) 14 { 15 return (cpx){a.x+b.x,a.y+b.y}; 16 } 17 cpx operator - (cpx a,cpx b) 18 { 19 return (cpx){a.x-b.x,a.y-b.y}; 20 } 21 cpx operator * (cpx a,cpx b) 22 { 23 double x1=a.x,x2=b.x,y1=a.y,y2=b.y; 24 return (cpx){x1*x2-y1*y2,x1*y2+x2*y1}; 25 } 26 double Sin[M],Cos[M]; 27 long long outp,cal,sm1,sm2; 28 int n,m,nm,rd,rev[N],lgg[N],ans[N]; 29 void read(int &x) 30 { 31 x=0; char ch=getchar(); 32 while(!isdigit(ch)) 33 ch=getchar(); 34 while(isdigit(ch)) 35 x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); 36 } 37 void prework() 38 { 39 register int i; 40 read(n),read(m); 41 for(i=1;i<=n;i++) 42 { 43 read(rd),sm1+=rd*rd,sm2+=rd; 44 a[i].x=a[i+n].x=rd; 45 } 46 for(i=1;i<=n;i++) 47 { 48 read(rd),sm1+=rd*rd,sm2-=rd; 49 b[n-i+1].x=rd; 50 } 51 cal=outp=1e9,nm=n,m=3*n,n=1,lgg[1]=0; while(n<=m) n<<=1; 52 for(i=2;i<=n;i++) 53 lgg[i]=lgg[i>>1]+1; 54 for(i=1;i<=n;i++) 55 rev[i]=(rev[i>>1]>>1)+(i&1)*(n>>1); 56 for(i=1;i<=24;i++) 57 Sin[i]=sin(2*pai/(1<<i)),Cos[i]=cos(2*pai/(1<<i)); 58 } 59 void transform(cpx *c,int t) 60 { 61 register int i,j,k; 62 for(i=0;i<n;i++) 63 if(rev[i]>i) swap(c[i],c[rev[i]]); 64 for(i=2;i<=n;i<<=1) 65 { 66 int len=i>>1; 67 cpx omg={Cos[lgg[i]],Sin[lgg[i]]*t}; 68 for(j=0;j<n;j+=i) 69 { 70 cpx ori={1,0},tmp; 71 for(k=j;k<j+len;k++,ori=ori*omg) 72 tmp=ori*c[k+len],c[k+len]=c[k]-tmp,c[k]=c[k]+tmp; 73 } 74 } 75 } 76 int main() 77 { 78 register int i; prework(); 79 transform(a,1),transform(b,1); 80 for(i=0;i<n;i++) a[i]=a[i]*b[i]; 81 transform(a,-1); 82 for(i=0;i<=2*nm;i++) ans[i]=(int)(a[i].x/n+0.5); 83 for(i=-m;i<=m;i++) cal=min(cal,sm1+1ll*i*i*nm+2ll*sm2*i); 84 for(i=1;i<=nm;i++) outp=min(outp,cal-2ll*ans[i+nm]); 85 printf("%lld",outp); 86 return 0; 87 }