HDU5213 Lucky【容斥+莫队】

HDU5213 Lucky

题意:

给出\(N\)个数和\(k\),有\(m\)次询问,每次询问区间\([L1,R1]\)和区间\([L2,R2]\)中分别取一个数能相加得到\(k\)的方案数

题解:

可以考虑容斥把两个区间的问题转化成四个单区间的问题,对于原问题给的区间\([L1,R1]\)\([L2,R2]\),我们记\(f(L,R)\)为区间\([L,R]\)内能相加得到\(k\)的有多少组合,那么对于每次的询问,可以简化为:\(f(L1,R1)+f(R1+1,L2-1)-f(L1,L2-1)-f(R1+1,R2)\)
对于这个\(f(L,R)\),可以使用莫队来解决

//#pragma GCC optimize("O3")
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<bits/stdc++.h>
using namespace std;
function<void(void)> ____ = [](){ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);};
const int MAXN = 1e5+7;
typedef long long int LL;
int n,k,m,A[MAXN],q,tot,cnt[MAXN];
LL ret[MAXN],ans;
class Query{
public:
    int op, id, l, r;
}Q[MAXN<<2];
void dec(int x){
    if(k>x) ans -= cnt[k-x];
    cnt[x]--;
}
void inc(int x){
    if(k>x) ans += cnt[k-x];
    cnt[x]++;
}
void solve(){
    scanf("%d",&k);
    for(int i = 1; i <= n; i++) scanf("%d",&A[i]);
    scanf("%d",&q);
    int tot = 0;
    for(int i = 1; i <= q; i++){
        int l1, r1, l2, r2;
        scanf("%d %d %d %d",&l1,&r1,&l2,&r2);
        tot++; Q[tot].id = i; Q[tot].l = l1; Q[tot].r = r2; Q[tot].op = 1;
        tot++; Q[tot].id = i; Q[tot].l = r1 + 1; Q[tot].r = l2 - 1; Q[tot].op = 1;
        tot++; Q[tot].id = i; Q[tot].l = l1; Q[tot].r = l2 - 1; Q[tot].op = -1;
        tot++; Q[tot].id = i; Q[tot].l = r1 + 1; Q[tot].r = r2; Q[tot].op = -1;
    }
    int sqt = sqrt(n);
    sort(Q+1,Q+1+tot,[&sqt](const Query &lhs, const Query &rhs){
        return lhs.l / sqt == rhs.l / sqt ? lhs.r < rhs.r : lhs.l / sqt < rhs.l / sqt;
    });
    ans = 0;
    memset(cnt,0,sizeof(cnt));
    memset(ret,0,sizeof(ret));
    int L = 1, R = 0;
    for(int i = 1; i <= tot; i++){
        while(L>Q[i].l) inc(A[--L]);
        while(R<Q[i].r) inc(A[++R]);
        while(L<Q[i].l) dec(A[L++]);
        while(R>Q[i].r) dec(A[R--]);
        ret[Q[i].id] += Q[i].op * ans;
    }
    for(int i = 1; i <= q; i++) printf("%I64d\n",ret[i]);
}
int main(){
    while(scanf("%d",&n)!=EOF) solve();
    return 0;
}
posted @ 2020-05-13 14:03  _kiko  阅读(81)  评论(0编辑  收藏  举报