BZOJ_2038
第一次写莫队了,之前偷懒一直没有写,听说还有一道历史观察啥的也可以做做,反正蛮水的。
但还是好好说一说。首先根号N分块,然后判断左端点在哪个块里面,按左端点的块为第一关键词,r为第二关键词排序。这样可以保证每一块里面r都是递增的。首先我们保证了r的复杂度是n根号哒,然后再是左端点,没跨过块的是根号,否则是暴力重建,还是根号哒。
所以总复杂度是n根号
1 #include <cstdio> 2 #include <iostream> 3 #include <cstdlib> 4 #include <algorithm> 5 #include <cstring> 6 #include <cmath> 7 using namespace std; 8 const int N = 50003; 9 struct qus { 10 int l,r,b,key; 11 }query[N],ans[N]; 12 int size,a[N],n,m,sta[N]; 13 long long fenzi,fenmu,gcdd; 14 inline bool cmp(qus x,qus y) { 15 if(x.b < y.b) return true; 16 if(x.b > y.b) return false; 17 return x.r < y.r; 18 } 19 inline long long gcd(long long a,long long b) { return b==0?a:gcd(b,a%b); } 20 int main() { 21 scanf("%d%d",&n,&m); 22 size = sqrt(n); 23 for(int i = 1 ; i <= n ; ++i) scanf("%d",&a[i]); 24 for(int i = 1 ; i <= m ; ++i) { 25 scanf("%d%d",&query[i].l,&query[i].r); 26 query[i].b = query[i].l/size; 27 query[i].key = i; 28 if(query[i].l%size!=0) query[i].b++; 29 } 30 sort(query+1,query+1+m,cmp); 31 for(int i = 1 ; i <= m ; ++i) { 32 if(i==1 || query[i].b!=query[i-1].b) { 33 memset(sta,0,sizeof(sta)); 34 fenzi = 0,fenmu = (query[i].r - query[i].l + 1) * (query[i].r - query[i].l); 35 for(int j = query[i].l ; j <= query[i].r ; ++j) sta[a[j]]++; 36 for(int j = 1 ; j <= n ; ++j) fenzi += sta[j]*(sta[j]-1); 37 gcdd = gcd(fenzi,fenmu); 38 } else { 39 fenmu = (query[i].r - query[i].l + 1) * (query[i].r - query[i].l); 40 for(int j = query[i-1].r+1; j <= query[i].r ; ++j) 41 fenzi += sta[a[j]]*2,sta[a[j]]++; 42 for(int j = query[i-1].l ; j < query[i].l ; ++j) 43 fenzi -= (sta[a[j]]-1)*2,sta[a[j]]--; 44 for(int j = query[i].l ; j < query[i-1].l ; ++j) 45 fenzi += sta[a[j]]*2,sta[a[j]]++; 46 gcdd = gcd(fenzi,fenmu); 47 } 48 ans[query[i].key].l = fenzi/gcdd; 49 ans[query[i].key].r = fenmu/gcdd; 50 } 51 for(int i = 1 ; i <= m ; ++i) printf("%d/%d\n",ans[i].l,ans[i].r); 52 }
这个代码还没有A啊,今天BZ挂了。贴上来玩耍