codeforces 877F Ann and Books

codeforces 877F Ann and Books

题目传送门

题意:

总共有\(n\)本书,每本书是数学的或者经济的。每本书中都有\(a_i\)个问题,给出\(q\)个询问,每次询问一个区间\([l,r]\)内,满足数学书的总问题比经济书的总问题多\(k\)个的子区间有多少个。
\((1 \leq n \leq 10^5, -10^9 \le k \leq 10^9,0 \leq a_i \leq 10^9,1 \leq q \leq 10^5)\)

题解:

首先我们考虑如何验证一个区间是否满足题目中的要求,我们可以先把所有的经济书的\(a_i\)置为\(-a_i\),这样我们只需要记一个前缀和就可以判断这个区间的数学书减经济书的值为多少了。然后我们考虑如何处理\(q\)个询问,由于题目没有强制在线,所以我们可以考虑用莫队去搞。先记\(sum[i]\)表示\(a\)的前缀和,然后可以用一个\(unordered\_map\)去记录当前前缀和为\(i\)的个数有多少个,然后我们每次移动\(l\)指针的时候,就减去或者加上\(Mp[sum[l-1]+k]\)的贡献,然后把\(Mp[sum[l-1]]++\)移动\(r\)指针的时候就减去或者加上\(Mp[sum[r]-k]\)的贡献,然后把\(Mp[sum[r]]++\)。不过可能是\(unordered\_map\)的常数有点大。。似乎是卡着过去的。。最好还是手写哈希吧。。

Code:

#pragma GCC diagnostic error "-std=c++11"
#pragma GCC target("avx")
#pragma GCC optimize(3)
#pragma GCC optimize("Ofast")
#pragma GCC optimize("inline")
#pragma GCC optimize("-fgcse")
#pragma GCC optimize("-fgcse-lm")
#pragma GCC optimize("-fipa-sra")
#pragma GCC optimize("-ftree-pre")
#pragma GCC optimize("-ftree-vrp")
#pragma GCC optimize("-fpeephole2")
#pragma GCC optimize("-ffast-math")
#pragma GCC optimize("-fsched-spec")
#pragma GCC optimize("unroll-loops")
#pragma GCC optimize("-falign-jumps")
#pragma GCC optimize("-falign-loops")
#pragma GCC optimize("-falign-labels")
#pragma GCC optimize("-fdevirtualize")
#pragma GCC optimize("-fcaller-saves")
#pragma GCC optimize("-fcrossjumping")
#pragma GCC optimize("-fthread-jumps")
#pragma GCC optimize("-funroll-loops")
#pragma GCC optimize("-fwhole-program")
#pragma GCC optimize("-freorder-blocks")
#pragma GCC optimize("-fschedule-insns")
#pragma GCC optimize("inline-functions")
#pragma GCC optimize("-ftree-tail-merge")
#pragma GCC optimize("-fschedule-insns2")
#pragma GCC optimize("-fstrict-aliasing")
#pragma GCC optimize("-fstrict-overflow")
#pragma GCC optimize("-falign-functions")
#pragma GCC optimize("-fcse-skip-blocks")
#pragma GCC optimize("-fcse-follow-jumps")
#pragma GCC optimize("-fsched-interblock")
#pragma GCC optimize("-fpartial-inlining")
#pragma GCC optimize("no-stack-protector")
#pragma GCC optimize("-freorder-functions")
#pragma GCC optimize("-findirect-inlining")
#pragma GCC optimize("-fhoist-adjacent-loads")
#pragma GCC optimize("-frerun-cse-after-loop")
#pragma GCC optimize("inline-small-functions")
#pragma GCC optimize("-finline-small-functions")
#pragma GCC optimize("-ftree-switch-conversion")
#pragma GCC optimize("-foptimize-sibling-calls")
#pragma GCC optimize("-fexpensive-optimizations")
#pragma GCC optimize("-funsafe-loop-optimizations")
#pragma GCC optimize("inline-functions-called-once")
#pragma GCC optimize("-fdelete-null-pointer-checks")
#include<bits/stdc++.h>
#include<tr1/unordered_map>
using namespace std;
typedef long long ll;
const int N=1e5+500;
tr1::unordered_map<ll,int>Mp;
int n,m,Sq,l,r;
int block[N];
ll a[N],sum[N];
ll k,res;
struct Query {
  int l,r,idx;
  ll ans;
  bool operator < (const Query &rhs) const {
    return block[l]==block[rhs.l]?r<rhs.r:block[l]<block[rhs.l];
  }
}q[N];

bool Cmp(Query a,Query b) {return a.idx<b.idx;}

int main() {
  scanf("%d%lld",&n,&k);
   Sq=sqrt(n)+100;
  for(int i=1;i<=n;i++) {
    scanf("%lld",&a[i]);
    block[i]=(i-1)/Sq+1;
    a[i]=a[i]==1?1:-1;
  }
  for(int i=1,x;i<=n;i++) {
    scanf("%d",&x);
    a[i]*=x;
    sum[i]=sum[i-1]+a[i];
  }
  scanf("%d",&m);
  for(int i=1;i<=m;i++) {
    scanf("%d%d",&q[i].l,&q[i].r);q[i].idx=i;
  }
  sort(q+1,q+1+m);
  l=1;r=0;
  Mp[0]=1;
  for(int i=1;i<=m;i++) {
    while(l<q[i].l) Mp[sum[l-1]]--,res-=Mp[sum[l-1]+k],l++;
    while(l>q[i].l) l--,res+=Mp[sum[l-1]+k],Mp[sum[l-1]]++;
    while(r<q[i].r) r++,res+=Mp[sum[r]-k],Mp[sum[r]]++;
    while(r>q[i].r) Mp[sum[r]]--,res-=Mp[sum[r]-k],r--;
    q[i].ans=res;
  }
  sort(q+1,q+1+m,Cmp);
  for(int i=1;i<=m;i++) {
    printf("%lld\n",q[i].ans);
  }
  return 0;
}
posted @ 2018-10-05 18:16  Apocrypha  阅读(220)  评论(0编辑  收藏  举报