This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
//sl : increase from l
//sr : increase from r
const int mx=300000,MID=150000,sq=100;
struct NN {
ll sum,sl,sr,cnt;
} s[1<<22];
int ccnt[mx+5],posi[mx+5],num[mx+5];
NN merge(NN a, NN b) {
NN res;
res.sum=a.sum+b.sum;
res.cnt=a.cnt+b.cnt;
res.sl=a.sl+a.cnt*b.sum+b.sl;
res.sr=b.sr+b.cnt*a.sum+a.sr;
return res;
}
void update(int l, int r, int idx, int x) {
if (x>r || x<l) return;
if (l==r) s[idx]={ccnt[l],ccnt[l],ccnt[l],1};
else {
int mid=(l+r)/2;
update(l,mid,2*idx,x);
update(mid+1,r,2*idx+1,x);
s[idx]=merge(s[2*idx],s[2*idx+1]);
}
}
NN query(int l, int r, int idx, int x, int y) {
if (x>r || y<l) return {0,0,0,0};
if (x<=l && r<=y) return s[idx];
int mid=(l+r)/2;
return merge(query(l,mid,2*idx,x,y),query(mid+1,r,2*idx+1,x,y));
}
int level[mx+5],have[mx+5],idx_seq=-1; //range of box that has been used
vector<int> seq;
deque<int> dq[mx+5];
ll ans=0;
void sw(int a, int b) {
swap(num[a],num[b]);
posi[num[a]]=a;
posi[num[b]]=b;
}
void add(int val) {
if (!have[val]) {
++idx_seq;
int pos=seq[idx_seq]; //the position of the seg-tree to be added
ccnt[pos]=1;
posi[val]=pos;
num[pos]=val;
update(1,mx,1,pos);
dq[1].push_back(pos);
ans+=query(1,mx,1,1,pos).sr+query(1,mx,1,pos,mx).sl-ccnt[pos];
} else {
int pos=posi[val], cnt=ccnt[pos]; //increase from cnt to cnt+1
int max_pos=dq[cnt].front();
sw(pos,max_pos);
//increase from cnt to cnt+1
dq[cnt].pop_front();
dq[cnt+1].push_back(max_pos);
++ccnt[max_pos];
update(1,mx,1,max_pos);
ans+=query(1,mx,1,1,max_pos).sr+query(1,mx,1,max_pos,mx).sl-ccnt[max_pos];
}
++have[val];
}
void del(int val) {
int pos=posi[val], cnt=ccnt[pos];
int min_pos=dq[cnt].back();
sw(pos,min_pos);
ans-=(query(1,mx,1,1,min_pos).sr+query(1,mx,1,min_pos,mx).sl-ccnt[min_pos]);
dq[cnt].pop_back();
if (cnt==1) --idx_seq;
else dq[cnt-1].push_front(min_pos);
--ccnt[min_pos];
update(1,mx,1,min_pos);
--have[val];
}
int n,q,a[mx+5];
struct Query {
int l,r,idx;
bool operator<(Query other) const {
return pii(l/sq,r)<pii(other.l/sq,other.r);
}
};
vector<Query> ques;
ll Ans[50005];
int main() {
ios_base::sync_with_stdio(0); cin.tie(0);
int ll=MID,rr=MID;
level[MID]=0;
seq.push_back(MID);
for (int i=1; i<mx; ++i) {
if (i%2==0) level[--ll]=i, seq.push_back(ll);
else level[++rr]=i, seq.push_back(rr);
}
cin>>n>>q;
for (int i=0; i<n; ++i) cin>>a[i];
for (int i=0; i<q; ++i) {
int l,r; cin>>l>>r;
ques.push_back({--l,--r,i});
}
sort(ques.begin(),ques.end());
int cur_l=0;
int cur_r=-1;
for (auto q : ques) {
while (cur_l>q.l) add(a[--cur_l]);
while (cur_r<q.r) add(a[++cur_r]);
while (cur_l<q.l) del(a[cur_l++]);
while (cur_r>q.r) del(a[cur_r--]);
Ans[q.idx]=ans;
}
for (int i=0; i<q; ++i) cout<<Ans[i]<<"\n";
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |