题目大意:
有$n(nle10^5)$个数$w_{1sim n}(|w_i|le10^9)$,并给定一个数$k(|k|le10^9)$。$q(qle10^5)$次询问,每次询问区间$[l,r]$中满足数字之和等于$k$的子区间数。
思路:
莫队卡常。
1 #pragma GCC optimize("Ofast") 2 #pragma GCC optimize("unroll-loops") 3 #include<cmath> 4 #include<cstdio> 5 #include<cctype> 6 #include<algorithm> 7 #include<unordered_map> 8 #include<tr1/unordered_map> 9 using int64=long long; 10 inline int getint() { 11 register char ch; 12 register bool neg=false; 13 while(!isdigit(ch=getchar())) neg|=ch=='-'; 14 register int x=ch^'0'; 15 while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0'); 16 return neg?-x:x; 17 } 18 constexpr int N=1e5+1,M=1e5; 19 int k,block; 20 int64 a[N],ans[N],tmp; 21 struct Query { 22 int l,r,id; 23 bool operator < (const Query &another) const { 24 return l/block==another.l/block?r<another.r:l/block<another.l/block; 25 } 26 }; 27 Query q[M]; 28 std::tr1::unordered_map<int64,int> map; 29 inline void ins(const int64 &x,const bool &b) { 30 tmp+=map[x-k*(b?1:-1)]; 31 map[x]++; 32 } 33 inline void del(const int64 &x,const bool &b) { 34 map[x]--; 35 tmp-=map[x-k*(b?1:-1)]; 36 } 37 int main() { 38 const int n=getint(); 39 block=sqrt(n)*2,k=getint(); 40 for(register int i=1;i<=n;i++) { 41 a[i]=getint()==1?1:-1; 42 } 43 for(register int i=1;i<=n;i++) { 44 (a[i]*=getint())+=a[i-1]; 45 } 46 const int m=getint(); 47 for(register int i=0;i<m;i++) { 48 const int l=getint()-1,r=getint(); 49 q[i]={l,r,i}; 50 } 51 std::sort(&q[0],&q[m]); 52 for(register int i=0,l=0,r=-1;i<m;i++) { 53 while(l>q[i].l) ins(a[--l],0); 54 while(r<q[i].r) ins(a[++r],1); 55 while(l<q[i].l) del(a[l++],0); 56 while(r>q[i].r) del(a[r--],1); 57 ans[q[i].id]=tmp; 58 } 59 for(register int i=0;i<m;i++) { 60 printf("%I64d%c",ans[i]," "[i==m-1]); 61 } 62 return 0; 63 }