Codeforces Round #442 (Div. 2) F. Ann and Books

来源:互联网 发布:删除excel中重复数据 编辑:程序博客网 时间:2024/05/17 00:52

F. Ann and Books

Problem Statement

    In Ann’s favorite book shop are as many as n books on math and economics. Books are numbered from 1 to n. Each of them contains non-negative number of problems.
    Today there is a sale: any subsegment of a segment from l to r can be bought at a fixed price.
    Ann decided that she wants to buy such non-empty subsegment that the sale operates on it and the number of math problems is greater than the number of economics problems exactly by k. Note that k may be positive, negative or zero.
    Unfortunately, Ann is not sure on which segment the sale operates, but she has q assumptions. For each of them she wants to know the number of options to buy a subsegment satisfying the condition (because the time she spends on choosing depends on that).
    Currently Ann is too busy solving other problems, she asks you for help. For each her assumption determine the number of subsegments of the given segment such that the number of math problems is greaten than the number of economics problems on that subsegment exactly by k.

Input

    The first line contains two integers n and k (1 ≤ n ≤ 100 000,  - 109 ≤ k ≤ 109) — the number of books and the needed difference between the number of math problems and the number of economics problems.
    The second line contains n integers t1, t2, …, tn (1 ≤ ti ≤ 2), where ti is 1 if the i-th book is on math or 2 if the i-th is on economics.
    The third line contains n integers a1, a2, …, an (0 ≤ ai ≤ 109), where ai is the number of problems in the i-th book.
    The fourth line contains a single integer q (1 ≤ q ≤ 100 000) — the number of assumptions.
    Each of the next q lines contains two integers li and ri (1 ≤ li ≤ ri ≤ n) describing the i-th Ann’s assumption.

Output

    Print q lines, in the i-th of them print the number of subsegments for the i-th Ann’s assumption.

Examples

Example 1
    Input
        4 1
        1 1 1 2
        1 1 1 1
        4
        1 2
        1 3
        1 4
        3 4
    Output
        2
        3
        4
        1
Example 2
    Input
        4 0
        1 2 1 2
        0 0 0 0
        1
        1 4
    Output
        10

Note

    In the first sample Ann can buy subsegments [1;1], [2;2], [3;3], [2;4] if they fall into the sales segment, because the number of math problems is greater by 1 on them that the number of economics problems. So we should count for each assumption the number of these subsegments that are subsegments of the given segment.
    Segments [1;1] and [2;2] are subsegments of [1;2].
    Segments [1;1], [2;2] and [3;3] are subsegments of [1;3].
    Segments [1;1], [2;2], [3;3], [2;4] are subsegments of [1;4].
    Segment [3;3] is subsegment of [3;4].

题意

    给出n本书,他们排成一个序列,书有两种类型,A类和B类,每本A类书的A类题是给出的,每本B类书的B类题也是给出的。现在有q组询问,每组询问询问一段区间[l,r],求这段区间内有多少个子区间满足A类题的总数比B类题多k道。

思路

    根据数据范围和多次查询来看,我们可以想到用莫队来做这道题。
    首先我们对于读入的数据进行预处理。因为我们要求A类题比B类题多k道,所以可以想到做前缀和,对于A类题我们把前缀和加上num[i],对于B类题我们把前缀和减去num[i],这样区间[l,r]的A类书比B类书多多少就可以用前缀和sum[r]-sum[l-1]来O(1)求出。之后对于现在所知道的区间[l,r],我们就可以快速求出[l-1,r],[l+1,r],[l,r-1],[l,r+1]四个区间所满足的值了,这就可以用伟大的莫队算法了。还有,因为前缀和的范围较大,所以这题需要离散化,但因为这题O(qn)的莫队如果再加上一个map的log可能会卡时间,于是我们应该先预处理出所有数的离散化之后的值然后用一个数组存一下O(1)查询就行了。

Code

#pragma GCC optimize(3)#include<bits/stdc++.h>using namespace std;typedef long long ll;bool Finish_read;template<class T>inline void read(T &x) {    Finish_read=0;x=0;int f=1;char ch=getchar();    while(!isdigit(ch)){if(ch=='-')f=-1;if(ch==EOF)return;ch=getchar();}    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();    x*=f;Finish_read=1;}template<class T>inline void print(T x) {    if(x/10!=0)        print(x/10);    putchar(x%10+'0');}template<class T>inline void writeln(T x) {    if(x<0)        putchar('-');    x=abs(x);    print(x);    putchar('\n');}template<class T>inline void write(T x) {    if(x<0)        putchar('-');    x=abs(x);    print(x);}/*================Header Template==============*/const int maxn=1000010;ll sum[maxn],nowans;int t[maxn],a[maxn],pos[3][maxn],cnt=0,n,k,q,type,block,tot[maxn];struct query{    int l,r,id;    ll ans;}w[maxn];map<ll,int>per;inline bool Cmp(query a,query b){return ((a.l-1)/block+1)==((b.l-1)/block+1)?a.r<b.r:a.l<b.l;}inline bool cmP(query a,query b){return a.id<b.id;}inline void update(int p,int x,int add) {    if(add==1) {        nowans+=tot[x];        tot[p]++;    }    else {        tot[p]--;        nowans-=tot[x];    }}int main() {    read(n);    read(k);    for(int i=1;i<=n;i++) {        read(type);        t[i]=(type==1)?1:-1;    }    for(int i=1;i<=n;i++) {        read(a[i]);        sum[i]=sum[i-1]+t[i]*a[i];    }    read(q);    for(int i=1;i<=q;i++) {        read(w[i].l);        read(w[i].r);        w[i].id=i;    }    block=sqrt(n);    sort(w+1,w+q+1,Cmp);    for(int i=0;i<=n;i++) {        per[sum[i]]=++cnt;        per[sum[i]-k]=++cnt;        per[sum[i]+k]=++cnt;    }    for(int i=0;i<=n;i++) {        pos[0][i]=per[sum[i]];        pos[1][i]=per[sum[i]+k];        pos[2][i]=per[sum[i]-k];    }    int l=1,r=0;    tot[per[0]]=1;    nowans=0;    for(int i=1;i<=q;i++) {        while(l<w[i].l) {            update(pos[0][l-1],pos[1][l-1],-1);            l++;        }        while(l>w[i].l) {            update(pos[0][l-2],pos[1][l-2],1);            l--;        }        while(r<w[i].r) {            update(pos[0][r+1],pos[2][r+1],1);            r++;        }        while(r>w[i].r) {            update(pos[0][r],pos[2][r],-1);            r--;        }        w[i].ans=nowans;    }    sort(w+1,w+q+1,cmP);    for(int i=1;i<=q;i++)        writeln(w[i].ans);    return 0;}