A simple question of "SNOI2017"
A simple solution
Obviously it can be differentiated.
\[
get(l,r,x)\times get(l1,r1,x)=get(1,r,x) \times get(1,r1,x)-get(1,l-1,x) \times get(1,r1,x)-get(1,r,x) \times get(1,l1-1,x)+get(1,l-1,x) \times get(1,l1-1,x)
\]
Since both of them start with 1, then remember two cnt arrays to represent the prefix, and then they can be divided into four intervals, Mo team.
#include <bits/stdc++.h> #define rep(q, a, b) for (int q = a, q##_end_ = b; q <= q##_end_; ++q) #define dep(q, a, b) for (int q = a, q##_end_ = b; q >= q##_end_; --q) #define mem(a, b) memset(a, b, sizeof a) #define debug(a) cerr << #a << ' ' << a << "___" << endl using namespace std; bool cur1; char buf[10000000], *p1 = buf, *p2 = buf; #define Getchar() p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 10000000, stdin), p1 == p2) ? EOF : *p1++ void in(int &r) { static char c; r = 0; while (c = Getchar(), c < 48) ; do r = (r << 1) + (r << 3) + (c ^ 48); while (c = Getchar(), c > 47); } const int mn = 50005; int K, n, val[mn]; long long ans[mn]; struct node { int l, r, id, ty; bool operator<(const node &A) const { return l / K == A.l / K ? (l / K & 1 ? r > A.r : r < A.r) : l / K < A.l / K; } } an[mn * 4]; int cnt[mn], cnt1[mn]; long long mid_ans; bool cur2; int main() { // cerr<<(&cur2-&cur1)/1024.0/1024<<endl; in(n); K = sqrt(n) + 1; rep(q, 1, n) in(val[q]); int Q; in(Q); int l, r, l1, r1; int ct = 0; rep(q, 1, Q) { in(l), in(r), in(l1), in(r1); an[++ct] = { r, r1, q, 1 }; if (l > 1) { an[++ct] = { l - 1, r1, q, -1 }; if (l1 > 1) an[++ct] = { l1 - 1, l - 1, q, 1 }; } if (l1 > 1) an[++ct] = { l1 - 1, r, q, -1 }; } sort(an + 1, an + ct + 1); l = 0, r = 0; rep(q, 1, ct) { while (l > an[q].l) mid_ans -= cnt1[val[l]], --cnt[val[l--]]; while (r < an[q].r) mid_ans += cnt[val[++r]], ++cnt1[val[r]]; while (l < an[q].l) mid_ans += cnt1[val[++l]], ++cnt[val[l]]; while (r > an[q].r) mid_ans -= cnt[val[r]], --cnt1[val[r--]]; ans[an[q].id] += mid_ans * an[q].ty; } rep(q, 1, Q) printf("%lld\n", ans[q]); return 0; }
Trouble solution
For two intervals \ ([l,r],[l1,r1](l \leq l1)), there are three types of inclusion and exclusion:
- No cross
- \([l1,r1] \) is contained by \ ([l,r] \)
- Two intervals intersect and have no inclusion relationship
For 1
\([l,r] \) value is K number has x, \ ([r+1,l1-1] \) value is K number has y, \ ([l1,r1] \) value is K number has z.
\[
xz= {(x+y+z)^2-(x+y)^2-(y+z)^2+y^2\over 2}
\]
Therefore, it can be divided into four sections for calculation.
For 2
\([l,l1-1] \) value is K number x, \ ([l1,r1] \) value is K number y, \ ([r1+1,r] \) value is K number z.
\[
y(x+y+z)={(x+y)^2+(y+z)^2-x^2-z^2 \over 2}
\]
Therefore, it can be divided into four sections for calculation.
For 3
\([l,l1-1] \) value is K number x, \ ([l1,r] \) value is K number y, \ ([r+1,r1] \) value is K number z.
\[
(x+y)(y+z)= {(x+y+z)^2-x^2-z^2+y^2\over 2}
\]
Therefore, it can be divided into four sections for calculation.
Sum up
Once more, we can calculate the sum of the squares of the same number in the interval.
#include<bits/stdc++.h> #define rep(q,a,b) for(int q=a,q##_end_=b;q<=q##_end_;++q) #define dep(q,a,b) for(int q=a,q##_end_=b;q>=q##_end_;--q) #define mem(a,b) memset(a,b,sizeof a ) #define debug(a) cerr<<#a<<' '<<a<<"___"<<endl using namespace std; bool cur1; char buf[10000000],*p1=buf,*p2=buf; #define Getchar() p1==p2&&(p2=(p1=buf)+fread(buf,1,10000000,stdin),p1==p2)?EOF:*p1++ void in(int &r) { static char c; r=0; while(c=Getchar(),c<48); do r=(r<<1)+(r<<3)+(c^48); while(c=Getchar(),c>47); } const int mn=50005; int K,n,val[mn]; long long ans[mn]; struct node{ int l,r,id,ty; bool operator <(const node &A)const{ return l/K==A.l/K?(l/K&1?r>A.r:r<A.r):l/K<A.l/K; } }an[mn*4]; int cnt[mn]; long long mid_ans; bool cur2; int main(){ // cerr<<(&cur2-&cur1)/1024.0/1024<<endl; in(n); K=sqrt(n)+1; rep(q,1,n)in(val[q]); int Q; in(Q); int l,r,l1,r1; int ct=0; rep(q,1,Q){ in(l),in(r),in(l1),in(r1); if(l>l1)swap(l,l1),swap(r,r1); if(r<l1){ an[++ct]={l,r1,q,1}; an[++ct]={l,l1-1,q,-1}; an[++ct]={r+1,r1,q,-1}; if(l1-1>=r+1)an[++ct]={r+1,l1-1,q,1}; }else if(r1<=r){ an[++ct]={l,r1,q,1}; an[++ct]={l1,r,q,1}; if(l<=l1-1)an[++ct]={l,l1-1,q,-1}; if(r1+1<=r)an[++ct]={r1+1,r,q,-1}; }else{ an[++ct]={l,r1,q,1}; an[++ct]={l1,r,q,1}; if(l<=l1-1)an[++ct]={l,l1-1,q,-1}; if(r+1<=r1)an[++ct]={r+1,r1,q,-1}; } } sort(an+1,an+ct+1); mid_ans=1,cnt[val[1]]=1; l=1,r=1; rep(q,1,ct){ while(l>an[q].l)--l,mid_ans+=(cnt[val[l]]++)<<1|1; while(r<an[q].r)++r,mid_ans+=(cnt[val[r]]++)<<1|1; while(l<an[q].l)mid_ans-=(--cnt[val[l]])<<1|1,++l; while(r>an[q].r)mid_ans-=(--cnt[val[r]])<<1|1,--r; ans[an[q].id]+=mid_ans*an[q].ty; } rep(q,1,Q)printf("%lld\n",ans[q]>>1); return 0; }