1. 程式人生 > >區間GCD

區間GCD

級別 復雜度 ble ios 思考 解法 是什麽 long long 限制

技術分享

輸入格式:

技術分享

輸出格式:

技術分享

樣例輸入:

glygshcyjcdzy
3
1 11
2 11
2 10

樣例輸出:

4
2
0

數據範圍:

技術分享

時間限制:

3S

空間限制:

512MB

這題是一個統計題.如果只是兩個字母,那就很好做了,然而,三個字母的話,很難直接統計.如果枚舉g,還藥確定c,d的相對位置,枚舉c和d也同樣.更何況有Q次詢問.

想到這題又是有多次詢問,也沒有修改操作,而且能在知道[L,R](或[L+1,R+1])的情況下知道[L+1,R]和[L,R+1],所以,我們確定,這題非常適合分塊+莫隊.更何況,時間復雜度也就在這個級別.

不會莫隊的童鞋請自行baidu一下(這一題有多種解法,如線段樹).

對於這一題,我們做莫隊的核心就是add和remove函數.

我們設g,c,d,gc,cd,gcd分別為這些串(g,c,d,gc,cd,gcd)在當前區間出現的次數.

如果來了一個字母或走了一個字母g,c,d,gc,cd,gcd要相應的更新,具體是什麽關系,思考一下就出來了,不在贅述(本蒟蒻不想丟人現眼qwq).

技術分享
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 #include<iostream>
 5
#include<cmath> 6 #define LL long long 7 using namespace std; 8 const int maxn=80005; 9 struct queries{int L,R,index; LL ans;}a[maxn]; 10 char s[maxn]; 11 int n,blocks,Q; 12 LL g,c,d,gc,cd,gcd,TT; 13 int read(){ 14 int x=0; char ch=getchar(); 15 while (ch<0||ch>9) ch=getchar();
16 while (ch>=0&&ch<=9) x=x*10+ch-0,ch=getchar(); 17 return x; 18 } 19 bool cmp(queries u,queries v){return u.L/blocks==v.L/blocks?u.R<v.R:u.L<v.L;} 20 bool cmp_id(queries u,queries v){return u.index<v.index;} 21 void removeL(int p,int q){ 22 if (s[p]==g) g--,gc-=c,gcd-=cd; else 23 if (s[p]==c) c--,cd-=d; else 24 if (s[p]==d) d--; 25 } 26 void removeR(int p,int q){ 27 if (s[q]==d) d--,cd-=c,gcd-=gc; else 28 if (s[q]==c) c--,gc-=g; else 29 if (s[q]==g) g--; 30 } 31 void addL(int p,int q){ 32 if (s[p]==g) g++,gc+=c,gcd+=cd; else 33 if (s[p]==c) c++,cd+=d; else 34 if (s[p]==d) d++; 35 } 36 void addR(int p,int q){ 37 if (s[q]==d) d++,cd+=c,gcd+=gc; else 38 if (s[q]==c) c++,gc+=g; else 39 if (s[q]==g) g++; 40 } 41 int main(){ 42 scanf("%s",s),n=strlen(s),blocks=sqrt(n),TT=(LL)2147483648LL; 43 for (int i=n; i>=1; i--) s[i]=s[i-1]; s[0]=0; 44 cin>>Q; for (int i=1; i<=Q; i++) a[i].L=read(),a[i].R=read(),a[i].index=i; 45 sort(a+1,a+1+Q,cmp); 46 int curL=1,curR=0; g=c=d=gc=cd=gcd=0; 47 for (int i=1; i<=Q; i++){ 48 while (curL<a[i].L) removeL(curL++,curR); 49 while (curR>a[i].R) removeR(curL,curR--); 50 while (curL>a[i].L) addL(--curL,curR); 51 while (curR<a[i].R) addR(curL,++curR); 52 a[i].ans=gcd%TT; 53 } 54 sort(a+1,a+1+Q,cmp_id); 55 for (int i=1; i<=Q; i++) printf("%lld\n",a[i].ans); 56 return 0; 57 }
View Code

區間GCD