題解 CF1605E Array Equalizer
阿新 • • 發佈:2021-12-05
首先將 \(a_i\) 變成 \(a_i-b_i\)
發現如果不管 \(a_1\) 的話,需要什麼操作是可以預處理出來的
然後單獨把 \(a_1\) 弄成0,需要什麼操作也是可以預處理出來的
要求最小化操作次數,發現這兩部分中有一些在同一位置的恰好相反的操作是可以消掉的
注意一個事情,若 \(a_1\) 恰好增加(或減少)1的話,其它任意位置需要的額外運算元不超過1
實際上位置 \(i\) 需要的操作是給這個位置加上一個 \(\mu(i)\),可以根據實際意義容斥證明
於是令 \(A\) 為當 \(a_i\) 增加1時需要進行加1操作的集合,\(B\) 為需要減1操作的集合
維護 \(val1\)
令 \(sum1\) 為 \(val1\) 的字首和
就會發現當 \(a_1\) 增加 \(x\) 時可以在 \(val1\) 中二分出一個分界點 \(t\)
可以消掉的運算元就是 \(2(sum1_t+x(|A|-t))\)
點選檢視程式碼
#include <bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define N 200010 #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], t[N]; int cge[N], val1[N], val2[N], val3[N], val4[N], top1, top2, top3, top4; ll sum1[N], sum2[N], sum3[N], sum4[N], sum, once=1, x; bool ina[N], inb[N], inc[N], ind[N]; signed main() { n=read(); for (int i=1; i<=n; ++i) a[i]=read(); for (int i=1; i<=n; ++i) b[i]=read(); for (int i=2; i<=n; ++i) a[i]-=b[i]; for (int i=2; i<=n; ++i) if (a[i]) { cge[i]=-a[i]; for (int j=i*2; j<=n; j+=i) a[j]-=a[i]; a[i]=0; } for (int i=2; i<=n; ++i) ++a[i]; for (int i=2; i<=n; ++i) if (a[i]) { ++once; if (a[i]<0) ina[i]=1; else inb[i]=1; for (int j=i*2; j<=n; j+=i) a[j]-=a[i]; a[i]=0; } for (int i=1; i<=n; ++i) sum+=abs(cge[i]); for (int i=1; i<=n; ++i) if (ina[i]&&cge[i]<0) val1[++top1]=abs(cge[i]); else if (ina[i]&&cge[i]>0) val3[++top3]=abs(cge[i]); else if (inb[i]&&cge[i]>0) val2[++top2]=abs(cge[i]); else if (inb[i]&&cge[i]<0) val4[++top4]=abs(cge[i]); sort(val1+1, val1+top1+1); sort(val2+1, val2+top2+1); sort(val3+1, val3+top3+1); sort(val4+1, val4+top4+1); for (int i=1; i<=top1; ++i) sum1[i]=sum1[i-1]+val1[i]; for (int i=1; i<=top2; ++i) sum2[i]=sum2[i-1]+val2[i]; for (int i=1; i<=top3; ++i) sum3[i]=sum3[i-1]+val3[i]; for (int i=1; i<=top4; ++i) sum4[i]=sum4[i-1]+val4[i]; #if 0 cout<<"val1: "; for (int i=1; i<=top1; ++i) cout<<val1[i]<<' '; cout<<endl; cout<<"val2: "; for (int i=1; i<=top2; ++i) cout<<val2[i]<<' '; cout<<endl; cout<<"val3: "; for (int i=1; i<=top3; ++i) cout<<val3[i]<<' '; cout<<endl; cout<<"val4: "; for (int i=1; i<=top4; ++i) cout<<val4[i]<<' '; cout<<endl; cout<<"cge: "; for (int i=1; i<=n; ++i) cout<<cge[i]<<' '; cout<<endl; #endif q=read(); while (q--) { x=a[1]-read(); if (x>0) { int t1=upper_bound(val3+1, val3+top3+1, x)-val3-1; int t2=upper_bound(val4+1, val4+top4+1, x)-val4-1; // cout<<"once: "<<once<<endl; // cout<<"sum: "<<sum<<endl; // cout<<"t: "<<t1<<' '<<t2<<endl; // cout<<sum3[t1]+(top3-t1)<<' '<<sum4[t2]+(top4-t2)<<endl; printf("%lld\n", sum+1ll*x*once-2ll*(sum3[t1]+x*(top3-t1)+sum4[t2]+x*(top4-t2))); } else if (x<0) { x=abs(x); int t1=upper_bound(val1+1, val1+top1+1, x)-val1-1; int t2=upper_bound(val2+1, val2+top2+1, x)-val2-1; // cout<<"once: "<<once<<endl; // cout<<"sum: "<<sum<<endl; // cout<<"t: "<<t1<<' '<<t2<<endl; printf("%lld\n", sum+1ll*x*once-2ll*(sum1[t1]+x*(top1-t1)+sum2[t2]+x*(top2-t2))); } else printf("%lld\n", sum); } return 0; }