官方題解c++
看了題解纔會作..git
首先考慮若是全部詢問的點都是[1,n]的作法,若是詢問是[l,r]只須要把多餘的去掉就行了數組
而後要把問題轉化爲一個點對其餘附近的點的貢獻spa
記$pre[i]$爲第i個位置的數字上一次出現的位置,記$nxt[i]$爲第i個位置上的數字下一次出現的位置,顯然這些東西都能掃一遍求出來code
而後對於一個點,它能作出貢獻的區間是:$$[\frac{pre[i]+i}{2}+1,\frac{i+nxt[i]}{2}]$$blog
若是不在這個區間內的話,顯然選擇$pre[i]$或者$nxt[i]$更優秀get
咱們把這個區間分紅兩份$$[\frac{pre[i]+i}{2}+1,i] and [i,\frac{i+nxt[i]}{2}]$$it
對於前一個區間這個點i對點j作出的貢獻爲$i-j$,對於後一個區間則爲$j-i$class
咱們維護兩個樹狀數組,一個記錄本身點上的座標被加/減了多少次,另外一個記錄這個點上被別的點貢獻了多少權值便可date
若是不是每次詢問[1,n]的話,咱們把詢問記錄下來,離線差分解決便可
1 #include<bits/stdc++.h> 2 #define int long long 3 #define inf (0x3f3f3f3f) 4 #define writeln(x) write(x),puts("") 5 #define writep(x) write(x),putchar(' ') 6 using namespace std; 7 inline int read(){ 8 int ans=0,f=1;char chr=getchar(); 9 while(!isdigit(chr)){if(chr=='-') f=-1;chr=getchar();} 10 while(isdigit(chr)){ans=(ans<<3)+(ans<<1)+chr-48;chr=getchar();} 11 return ans*f; 12 }void write(int x){ 13 if(x<0) putchar('-'),x=-x; 14 if(x>9) write(x/10); 15 putchar(x%10+'0'); 16 }const int M = 2e5+5; 17 int n,nxt[M],pre[M],T,cnt[M],a[M],ans[M]; 18 struct Que{int pos,opt,id;}; 19 struct P{int s[M]; 20 #define lowbit(x) (x&-x) 21 inline void Update(int x,int y){for(;x<=n;x+=lowbit(x))s[x]+=y;} 22 inline int Query(int x,int ans=0){for(;x;x-=lowbit(x))ans+=s[x];return ans;} 23 inline void Update(int l,int r,int x){Update(l,x),Update(r+1,-x);} 24 #undef lowbit 25 }T1,T2;vector<int>tp[M];vector<Que>Q[M]; 26 inline void Update(int i){ 27 int l=(pre[i]+i>>1)+1;if(l<1)l=1; 28 T1.Update(l,i,i),T2.Update(l,i,-1); 29 int r=nxt[i]+i>>1;if(r>n)r=n; 30 T1.Update(i,r,-i),T2.Update(i,r,1); 31 }inline int Query(int pos){ 32 return T2.Query(pos)*pos+T1.Query(pos); 33 }signed main(){ 34 n=read(),T=read(); 35 for(int i=1;i<=n;i++){ 36 a[i]=read();pre[i]=-inf,nxt[i]=inf; 37 if(tp[a[i]].size()) nxt[pre[i]=*tp[a[i]].rbegin()]=i; 38 tp[a[i]].push_back(i); 39 }for(int i=1;i<=T;i++){ 40 int pos=read(),l=read(),r=read(); 41 Q[l-1].push_back((Que){pos,-1,i}); 42 Q[r].push_back((Que){pos,1,i}); 43 }for(int i=1;i<=n;i++){ 44 for(int pos:tp[i])Update(pos); 45 for(Que now:Q[i]) ans[now.id]+=now.opt*Query(now.pos); 46 }for(int i=1;i<=T;i++)printf("%lld\n",ans[i]); 47 return 0; 48 }