zoukankan      html  css  js  c++  java
  • 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
    ",ret[i]);
    }
    int main(){
        while(scanf("%d",&n)!=EOF) solve();
        return 0;
    }
    
  • 相关阅读:
    JavaScript中运算符的优先级
    JS中在当前日期上追加一天或者获取上一个月和下一个月
    Window命令行工具操作文件
    多线程Worker初尝试
    基于gulp的前端自动化开发构建新
    cURL和file_get_contents实现模拟post请求
    Thinkphp5使用validate实现验证功能
    微信小程序wx.pageScrollTo的替代方案
    js设计模式之代理模式以及订阅发布模式
    js设计模式之单例模式
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12882007.html
Copyright © 2011-2022 走看看