題目
首先容斥轉化爲求刪掉的數的個數。
考慮若是所選的區間內不存在重數怎麼作。
先離散化。
而後咱們須要對每一個詢問求其刪掉的數。
把每一個詢問拆成3個區間跑莫隊。
跑的時候用bitset記錄當前區間內有哪些數就好了。
考慮如何處理重數的問題。
設\(i\)在序列中出現的次數爲\(cnt_i\)。
顯然\(\sum cnt=n\)。而且任意區間中\(i\)出現的次數不會超過\(cnt_i\)。
對於沒有重數的bitset,\(i\)佔據的是\(i\)這個位置。
而如今有重數了,咱們就讓\(i\)佔據\(\sum\limits_{j=1}^{i-1}cnt_j+1\)到\(\sum\limits_{j=1}^icnt_j\)的位置。
同時咱們實時維護一個\(pos_i\)表示下一個\(i\)佔據的位置。
具體而言,第\(j\)個\(i\)將佔據\(\sum\limits_{k=1}^{i-1}cnt_k+j\)的位置。
由於咱們給每一個\(i\)都分配了剛好\(cnt_i\)的位置。
因此這個bitset的大小依舊是\(n\),而且不一樣的數不可能佔據相同的位置。
並且對於\(i\),它必定先佔據能佔據的前面的位置。
因此這樣作必定是正確的。
而後你就會發現你開不下這麼多bitset。
因此咱們把詢問拆成\(3-4\)組跑就沒問題了。
實現上有一些小trick。node
#include<bits/stdc++.h> #define mp make_pair #define P pair<int,int> #define fir first #define sec second using namespace std; namespace IO { char ibuf[(1<<21)+1],obuf[(1<<21)+1],st[15],*iS,*iT,*oS=obuf,*oT=obuf+(1<<21); char Get(){return (iS==iT? (iT=(iS=ibuf)+fread(ibuf,1,(1<<21)+1,stdin),(iS==iT? EOF:*iS++)):*iS++);} void Flush(){fwrite(obuf,1,oS-obuf,stdout),oS=obuf;} void Put(char x){*oS++=x;if(oS==oT)Flush();} int read(){int x=0;char ch=Get();while(ch>57||ch<48)ch=Get();while(ch>=48&&ch<=57)x=x*10+(ch^48),ch=Get();return x;} void write(int x){int top=0;if(!x)Put('0');while(x)st[++top]=(x%10)+48,x/=10;while(top)Put(st[top--]);Put('\n');} } using namespace IO; const int N=100007,M=25007,S=300; int a[N],bel[N],pos[N],sum[M],vis[M]; P t[N]; bitset<N>s[M],del; struct node{int l,r,id;}q[M*3]; int operator<(node a,node b){return bel[a.l]^bel[b.l]? a.l<b.l:a.r<b.r;} void solve(int m) { memset(vis,0,sizeof vis),memset(sum,0,sizeof sum); int tot=0,i,l,r,j; for(i=1;i<=m;++i) for(j=0;j<=2;++j) l=read(),r=read(),q[++tot]=(node){l,r+1,i},sum[i]+=r+1-l; sort(q+1,q+tot+1),q[++tot]=(node){1,1,0}; for(del.reset(),i=l=r=1;i<=tot;++i) { while(r<q[i].r) del[++pos[a[r]]]=1,++r; while(l>q[i].l) --l,del[++pos[a[l]]]=1; while(r>q[i].r) --r,del[pos[a[r]]--]=0; while(l<q[i].l) del[pos[a[l]]--]=0,++l; vis[q[i].id]? s[q[i].id]&=del:(vis[q[i].id]=1,s[q[i].id]=del); } for(i=1;i<=m;++i) write(sum[i]-s[i].count()*3); } int main() { int i,k,n=read(),m=read(); for(i=1;i<=n;++i) a[i]=read(),t[i]=mp(a[i],i),bel[i]=i/S; sort(t+1,t+n+1); for(i=1,k=0;i<=n;++i) a[t[i].sec]=t[i].fir==t[i-1].fir? k:++k; for(i=1;i<=n;++i) if(t[i].fir^t[i-1].fir) pos[a[t[i].sec]]=i; while(m) m<=25000? (solve(m),m=0):(solve(25000),m-=25000); return Flush(),0; }