BZOJ5016[Snoi2017]一個簡單的詢問
阿新 • • 發佈:2019-03-19
sum tchar bound times struct bzoj zoj mes pac
\(=Q(r1,r2)-Q(r1,l2-1)-Q(l1-1,r2)+Q(l1-1,l2-1)\)
BZOJ5016[Snoi2017]一個簡單的詢問
題面:BZOJ
解析
這題的ider挺有意思的。看看數據範圍,多半是莫隊,但直接統計答案又不行(有4個參數啊),來拆式子,設\(Q(i,j)=\sum_{x=0}^{\infty}cnt[0..i][x]\times cnt[0..j][x]\),這個是可以用莫隊做的,那怎麽用它把題中的式子表示出來呢?有:
\(ans(l1,r1,l2,r2)\)
\(=\sum_{x=0}^{\infty}cnt[l1..r1][x]\times cnt[l2..r2][x]\)
\(=\sum_{x=0}^{\infty}(cnt[0..r1][x]-cnt[0..l1-1][x])\times (cnt[0..r2][x]-cnt[0..l2-1][x])\)
\(=Q(r1,r2)-Q(r1,l2-1)-Q(l1-1,r2)+Q(l1-1,l2-1)\)
代碼
#include<cmath> #include<cstdio> #include<algorithm> #define N 50005 #define LL long long using namespace std; inline int In(){ char c=getchar(); int x=0,ft=1; for(;c<'0'||c>'9';c=getchar()) if(c=='-') ft=-1; for(;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0'; return x*ft; } int n,m,a[N],t[N],tc,id[N][4],bc,cnt[N][2],qc=0; LL res=0,ans[N*4]; struct Q{ int l,r,id; }q[N*4]; inline bool cmp(Q a,Q b){ return a.l/bc==b.l/bc?a.r<b.r:a.l<b.l; } inline void add(int x,int C){ res+=cnt[a[x]][C^1]; ++cnt[a[x]][C]; } inline void del(int x,int C){ res-=cnt[a[x]][C^1]; --cnt[a[x]][C]; } int main(){ n=In(); for(int i=1;i<=n;++i) t[i]=a[i]=In(); m=In(); sort(t+1,t+1+n); tc=unique(t+1,t+1+n)-t-1; for(int i=1;i<=n;++i) a[i]=lower_bound(t+1,t+1+tc,a[i])-t; for(int i=1,l1,r1,l2,r2;i<=m;++i){ l1=In(); r1=In(); l2=In(); r2=In(); q[++qc]=(Q){r1,r2,qc}; id[i][0]=qc; q[++qc]=(Q){r1,l2-1,qc}; id[i][1]=qc; q[++qc]=(Q){l1-1,r2,qc}; id[i][2]=qc; q[++qc]=(Q){l1-1,l2-1,qc}; id[i][3]=qc; } bc=(int)(1.0*n/sqrt(2.0*qc/3.0)+0.5); sort(q+1,q+1+qc,cmp); int nl=0,nr=0; cnt[0][0]=cnt[0][1]=1; res=1; for(int i=1,ql,qr;i<=qc;++i){ ql=q[i].l; qr=q[i].r; while(ql<nl) del(nl--,0); while(ql>nl) add(++nl,0); while(qr<nr) del(nr--,1); while(qr>nr) add(++nr,1); ans[q[i].id]=res-1; } for(int i=1;i<=m;++i) printf("%lld\n",ans[id[i][0]] -ans[id[i][1]]-ans[id[i][2]]+ans[id[i][3]]); return 0; }
BZOJ5016[Snoi2017]一個簡單的詢問