莫队-作业(题名就是作业)
作业这道题,先不说题面,一看时间限制10000ms每个测试点,然后就出现了一系列的机惨行为,首先是机房最后一排集体交作业,导致评测机负载过大,同时卡了10个评测,然后,一天后也就是今天,我刚一看体,就想到一个$ O(n*m*log(n)) $的暴力,所以自己竟然鼓起勇气交了,但是,第一遍交没有删除freopen,导致200000ms打满,然后在我发现之后又删掉叫了一个,总共两个程序卡了5分钟!(我在这里接受你们的谴责,只要别打脸,别踢裆,咋都行)
然后,说正解!
这道题是莫队和分快的巧妙结合,其实树状数组也可以进行工作,但是经过本人缜(che)密(dan)的分(y)析(y),发现分快的复杂度会低,所以果断使用分快,使用分快维护答案,因为莫队就是分快的思想所以这个莫对和分快很好的结合,其实就是一道水题,我也相信这篇3分钟打的博客也没人看,我主要就是纪念一下这次的机惨
我错了!
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<cstdlib> 6 #include<algorithm> 7 #define debug(x) cout<<x<<" debug!"<<endl; 8 using namespace std; 9 const int L=1<<20|1; 10 char buffer[L],*S,*T; 11 #define getchar() ((S==T&&(T=(S=buffer)+fread(buffer,1,L,stdin),S==T))?EOF:*S++) 12 int n,m,pos[3000000],cnt[3000000],blk,s[3000000],g[3000000],ll[3000000],rr[3000000],f[3000000]; 13 struct mo{ 14 int l,r,res1,res2,id,a,b; 15 }G[3000000]; 16 inline int read() 17 { 18 int ss=0;char bb=getchar(); 19 while(bb<48||bb>57)bb=getchar(); 20 while(bb>=48&&bb<=57)ss=(ss<<1)+(ss<<3)+(bb^48),bb=getchar(); 21 return ss; 22 } 23 bool cmp(mo a,mo b){return pos[a.l]==pos[b.l]?a.r<b.r:a.l<b.l;} 24 bool co(mo a,mo b){return a.id<b.id;} 25 void add(int x) 26 { 27 ++f[pos[x]]; 28 ++cnt[x]; 29 if(cnt[x]==1)g[pos[x]]++; 30 } 31 void rmo(int x) 32 { 33 --f[pos[x]]; 34 --cnt[x]; 35 if(!cnt[x])g[pos[x]]--; 36 } 37 void make(int l,int r,int x) 38 { 39 if(pos[l]==pos[r]) 40 { 41 for(int i=l;i<=r;i++) 42 if(cnt[i]) 43 G[x].res1+=cnt[i],G[x].res2++; 44 } 45 else 46 { 47 for(int i=l;i<=rr[pos[l]];i++)if(cnt[i])G[x].res1+=cnt[i],G[x].res2++; 48 for(int i=ll[pos[r]];i<=r;i++)if(cnt[i])G[x].res1+=cnt[i],G[x].res2++; 49 for(int i=pos[l]+1;i<=pos[r]-1;i++)G[x].res1+=f[i],G[x].res2+=g[i]; 50 } 51 } 52 int main() 53 { 54 //freopen("re.cpp","r",stdin); 55 n=read(),m=read(); 56 blk=sqrt(n)+1; 57 //debug(blk); 58 int ccp=0; 59 for(int i=1;i<=n;i++) 60 { 61 if(i%blk==1)++ccp,ll[ccp]=i; 62 pos[i]=ccp; 63 //debug(123); 64 if(i%blk==0)rr[ccp]=i; 65 } 66 /*debug(456); 67 for(int i=1;i<=n;i++) 68 printf("%d ",pos[i]); 69 puts("");*/ 70 for(int i=1;i<=n;i++) 71 s[i]=read(); 72 for(int i=1;i<=m;i++) 73 G[i].l=read(),G[i].r=read(),G[i].a=read(),G[i].b=read(),G[i].id=i; 74 sort(G+1,G+m+1,cmp); 75 int l=1,r=0; 76 for(int i=1;i<=m;i++) 77 { 78 while(l>G[i].l) add(s[--l]); 79 while(l<G[i].l) rmo(s[l++]); 80 while(r<G[i].r) add(s[++r]); 81 while(r>G[i].r) rmo(s[r--]); 82 make(G[i].a,G[i].b,i); 83 } 84 sort(G+1,G+m+1,co); 85 for(int i=1;i<=m;i++) 86 { 87 printf("%d %d\n",G[i].res1,G[i].res2); 88 } 89 return 0; 90 }
自带卡常优化!