Pre knowledge
Example 1: Little Z's socks
Note that cnt[i]cnt[i]cnt[i] is the frequency of color iii, then our answer is
∑cnt[i](cnt[i]−1)(R−L+1)(R−L)\frac{\sum cnt[i](cnt[i]-1)}{(R-L+1)(R-L)}(R−L+1)(R−L)∑cnt[i](cnt[i]−1)
=(cnt[1]2+cnt[2]2+...+cnt[n]2)−(cnt[1]+cnt[2]+...+cnt[n])(R−L+1)(R−L)=\frac{(cnt[1]^2+cnt[2]^2+...+cnt[n]^2)-(cnt[1]+cnt[2]+...+cnt[n])}{(R-L+1)(R-L)}=(R−L+1)(R−L)(cnt[1]2+cnt[2]2+...+cnt[n]2)−(cnt[1]+cnt[2]+...+cnt[n])
=(cnt[1]2+cnt[2]2+...+cnt[n]2)−(R−L+1)(R−L+1)(R−L)=\frac{(cnt[1]^2+cnt[2]^2+...+cnt[n]^2)-(R-L+1)}{(R-L+1)(R-L)}=(R−L+1)(R−L)(cnt[1]2+cnt[2]2+...+cnt[n]2)−(R−L+1)
Code
#include<bits/stdc++.h> #define int long long using namespace std; struct que{ int l,r,id,pos; long long a,b; }ans[50005]; int n,m,f[50005],base,nw=0,cnt[500005],pos[50005]; bool cmp1(que x,que y){ if(pos[x.l]==pos[y.l]) return x.r<y.r; return x.l<y.l; } bool cmp2(que x,que y){ return x.id<y.id; } void update(int p,int add) { nw-=cnt[f[p]]*cnt[f[p]]; cnt[f[p]]+=add; nw+=cnt[f[p]]*cnt[f[p]]; } int gcd(int a,int b){ return (a%b==0)?b:gcd(b,a%b); } void solve(){ for(int i=1,l=1,r=0;i<=m;i++){ while(r<ans[i].r) update(++r,1); while(r>ans[i].r) update(r--,-1); while(l<ans[i].l) update(l++,-1); while(l>ans[i].l) update(--l,1); if(ans[i].l==ans[i].r){ ans[i].a=0; ans[i].b=1; continue; } ans[i].a=nw-(r-l+1),ans[i].b=(r-l+1)*(r-l); long long C=gcd(ans[i].a,ans[i].b); ans[i].a/=C;ans[i].b/=C; } } signed main(){ scanf("%lld%lld",&n,&m); for(int i=1;i<=n;i++){ scanf("%lld",&f[i]); } base=sqrt(n); for(int i=1;i<=n;i++){ pos[i]=(i-1)/base+1; } for(int i=1;i<=m;i++){ scanf("%lld%lld",&ans[i].l,&ans[i].r); ans[i].id=i; } sort(ans+1,ans+m+1,cmp1); solve(); sort(ans+1,ans+m+1,cmp2); for(int i=1;i<=m;i++){ cout<<ans[i].a<<"/"<<ans[i].b<<"\n"; } }
Example 2: Little B's question
Method the same as example 111, the code is omitted.
Example 3: File management of Mato
First, simplify the meaning of the question: given a sequence, find the logarithm of the reverse order pairs between [L,R][L,R][L,R].
With the idea of simplifying the question, the problem is very easy to deal with. We use the weight tree array to find the reverse order pair. Each time we expand the range, we increase the weight of the number by 111, and then reduce the number by 111 when we shrink the range. By the way, we can increase or decrease the corresponding contribution.
Code
#include<bits/stdc++.h> #define lowbit(x) (x&(-x)) using namespace std; int Read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } struct que{ int l,r,id; }q[50005]; int n,m,a[100005],b[100005],base,belong[100005],L[1005],R[1005],cnt=0; int c[100005],ans[100005],ct; bool operator < (que x,que y){ if(belong[x.l]!=belong[y.l]) return belong[x.l]<belong[y.l]; return x.r<y.r; } void Add(int x,int p){ while(x<=n){ c[x]+=p; x+=lowbit(x); } } int query(int x){ int res=0; while(x>=1){ res+=c[x]; x-=lowbit(x); } return res; } void solve(){ int l=1,r=0; for(int i=1;i<=m;i++){ while(q[i].l<l) l--,Add(a[l],1),ct+=query(a[l]-1); while(q[i].l>l) Add(a[l],-1),ct-=query(a[l]-1),l++; while(q[i].r<r) Add(a[r],-1),ct-=r-l-query(a[r]),r--; while(q[i].r>r) r++,Add(a[r],1),ct+=r-l+1-query(a[r]); ans[q[i].id]=ct; } for(int i=1;i<=m;i++) cout<<ans[i]<<endl; } int main(){ n=Read();base=sqrt(n); for(int i=1;i<=n;i++) a[i]=Read(),b[i]=a[i]; sort(b+1,b+n+1); int Q=unique(b+1,b+n+1)-b-1; for(int i=1;i<=n;i++) a[i]=lower_bound(b+1,b+Q+1,a[i])-b; m=Read(); for(int i=1;i<=m;i++){ q[i].l=Read();q[i].r=Read(); q[i].id=i; } for(int i=1;i<=n;i+=base){ L[++cnt]=i;R[cnt]=i+base-1; } R[cnt]=n; for(int i=1;i<=cnt;i++){ for(int j=L[i];j<=R[i];j++){ belong[j]=i; } } sort(q+1,q+m+1); solve(); return 0; }
Example 4: Gty's binary sister sequence
Method 1 (O (n n log n))(O(n\sqrt n\log n))(O(nn logn)):
The interval [a,b][a,b][a,b] is divided into [1,a − 1][1,a-1][1,a − 1] and [1,b][1,b][1,b]. When a new number x x x is added, the values of [x,b][x,b][x,b] are all + 1 + 1 + 1 using data structures such as line tree, which can be counted during query.
Method 2: (O (n n)) (O (n \ sqrt n)) (O (NN)):
Use the value field to block. The writing method is the same as the necklace of HH. Record whether each number appears. If it appears, modify the number in the block and the total type number of the block according to O(1)O(1)O(1). Finally, count in O(n)O(\sqrt n)O(n).
Code
#include<bits/stdc++.h> using namespace std; int Read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } int n,m,a[100005],base,L[1005],R[1005],belong[100005],cnt=0,ans[1000005]; int sum[100005],s[100005],ss[100005]; struct que{ int l,r,a,b,id; }q[1000005]; bool operator < (que x,que y){ if(belong[x.l]!=belong[y.l]) return belong[x.l]<belong[y.l]; return x.r<y.r; } void Del(int pos){ s[a[pos]]--; if(s[a[pos]]==0) sum[belong[a[pos]]]--,ss[a[pos]]=0; } void Ins(int pos){ s[a[pos]]++; if(s[a[pos]]==1) sum[belong[a[pos]]]++,ss[a[pos]]=1; } int calc(int l,int r){ int l1=belong[l],r1=belong[r],res=0; for(int i=l1+1;i<=r1-1;i++){ res+=sum[i]; } for(int i=l;i<=min(R[l1],r);i++){ res+=ss[i]; } if(r<=R[l1]) return res; for(int i=L[r1];i<=r;i++) res+=ss[i]; return res; } void solve(){ int l=1,r=0; for(int i=1;i<=m;i++){ while(q[i].l>l) Del(l++); while(q[i].l<l) Ins(--l); while(q[i].r<r) Del(r--); while(q[i].r>r) Ins(++r); ans[q[i].id]=calc(q[i].a,q[i].b); } for(int i=1;i<=m;i++){ cout<<ans[i]<<endl; } } int main(){ n=Read(),m=Read(); for(int i=1;i<=n;i++) a[i]=Read(); for(int i=1;i<=m;i++){ q[i].l=Read(),q[i].r=Read(); q[i].a=Read(),q[i].b=Read(); q[i].id=i; } base=sqrt(n); for(int i=1;i<=n;i+=base){ L[++cnt]=i,R[cnt]=i+base-1; } R[cnt]=n; for(int i=1;i<=cnt;i++){ for(int j=L[i];j<=R[i];j++){ belong[j]=i; } } sort(q+1,q+m+1); solve(); return 0; }
Example 5: [HNOI2016] series
Suppose we have got the answer of interval [L,R][L,R][L,R], then the answer of interval [L,R+1][L,R+1][L,R+1] is to add interval [L,R+1],[L+1,R+1],...,[R,R+1][L,R+1],[L+1,R+1],...,[R,R+1][L,R+1],[L+1,R+1],...,[R,R+1] and a [R + 1] a [R + 1].
[pre [i]] + (I − pre[i]+1) × a[i].
After finding out these, we can start to solve our problems. Note that the position of the minimum value of the interval is posposo (using ST table), then the answer of the interval [L,R][L,R][L,R] is
ans=a[R]×(R−pre[R]+1)+a[pre[R]]×(pre[R]−pre[pre[R]]+1)+...+a[pos]∗(pos−L+1)ans=a[R]\times(R-pre[R]+1)+a[pre[R]]\times(pre[R]-pre[pre[R]]+1)+...+a[pos]*(pos-L+1)ans=a[R]×(R−pre[R]+1)+a[pre[R]]×(pre[R]−pre[pre[R]]+1)+...+a[pos]∗(pos−L+1)
Through the calculation of fff, we can know:
f[R]−f[pos]=a[R]×(R−pre[R]+1)+a[pre[R]]×(pre[R]−pre[pre[R]]+1)+...f[R]-f[pos]=a[R]\times(R-pre[R]+1)+a[pre[R]]\times(pre[R]-pre[pre[R]]+1)+...f[R]−f[pos]=a[R]×(R−pre[R]+1)+a[pre[R]]×(pre[R]−pre[pre[R]]+1)+...
Since there must be a number of pre=pospre=pospre=pos, the above formula always holds.
Then, from the above two formulas, we can get
ans=f[R]−f[pos]+a[pos]∗(pos−L+1)ans=f[R]-f[pos]+a[pos]*(pos-L+1)ans=f[R]−f[pos]+a[pos]∗(pos−L+1)
Preprocessing the fff and ST tables can complete the insertion on the right within the O(1)O(1)O(1) O (1) time, and subtracting the inserted contribution when deleting.
The symmetry processing on the left is enough.
Note: team Mo here needs to expand and then shrink, otherwise there will be metaphysical mistakes.
Code
#include<bits/stdc++.h> #define int long long using namespace std; int Read(){ int x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();} while(isdigit(ch)){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} return x*f; } int a[100005],ans[100005],minn[100005][20],n,m,pre[100005],suf[100005]; int base,belong[100005],L[1005],R[1005],cnt=0,s[100005],tp=0; struct que{ int l,r,id; }q[100005]; bool operator < (que x,que y){ if(belong[x.l]!=belong[y.l]) return belong[x.l]<belong[y.l]; return x.r<y.r; } int my_min(int x,int y){ return (a[x]<a[y])?x:y; } void ST(){ for(int j=1;(1<<j)<=n;j++){ for(int i=1;i+(1<<j)-1<=n;i++){ minn[i][j]=my_min(minn[i][j-1],minn[i+(1<<(j-1))][j-1]); } } } int query(int l,int r){ int k=log(r-l+1)/log(2); return my_min(minn[l][k],minn[r-(1<<k)+1][k]); } namespace s1{ int f[100005]; void prework(){ for(int i=1;i<=n;i++){ f[i]=f[pre[i]]+(i-pre[i])*a[i]; } } int calc(int l,int r){ int pos=query(l,r+1); return (pos-l+1)*a[pos]+f[r+1]-f[pos]; } } namespace s2{ int f[100005]; void prework(){ for(int i=n;i>=1;i--){ f[i]=f[suf[i]]+(suf[i]-i)*a[i]; } } int calc(int l,int r){ int pos=query(l-1,r); return (r-pos+1)*a[pos]+f[l-1]-f[pos]; } } int res=0; void solve(){ int l=1,r=0; for(int i=1;i<=m;i++){ while(r<q[i].r) res+=s1::calc(l,r++); while(l>q[i].l) res+=s2::calc(l--,r); while(r>q[i].r) res-=s1::calc(l,--r); while(l<q[i].l) res-=s2::calc(++l,r); ans[q[i].id]=res; } for(int i=1;i<=m;i++) printf("%lld\n",ans[i]); } signed main(){ n=Read(),m=Read(); for(int i=1;i<=n;i++){ a[i]=Read(); minn[i][0]=i; } ST(); for(int i=1;i<=n;i++){ while(tp&&a[s[tp]]>a[i]) suf[s[tp--]]=i; pre[i]=s[tp],s[++tp]=i; } while(tp) pre[s[tp]]=s[tp-1],suf[s[tp--]]=n+1; s1::prework(); s2::prework(); base=sqrt(n); for(int i=1;i<=n;i+=base){ L[++cnt]=i,R[cnt]=i+base-1; } R[cnt]=n; for(int i=1;i<=cnt;i++){ for(int j=L[i];j<=R[i];j++){ belong[j]=i; } } for(int i=1;i<=m;i++){ q[i].l=Read(),q[i].r=Read(); q[i].id=i; } sort(q+1,q+m+1); solve(); return 0; }