• 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;
    }
    
  • 相关阅读:
    iOS:Core Data 中的简单ORM
    Win8:Snap 实现
    js: 删除node的所有child
    WinJS:Listview item 设置背景透明
    iOS: 消息通信中的Notification&KVO
    win8: 清除iframe的缓存
    What's New in iOS7,iOS7新特性介绍
    "Entity Framework数据插入性能追踪"读后总结
    夜,思考——我想要的到底是什么?
    【查询】—Entity Framework实例详解
  • 原文地址:https://www.cnblogs.com/kikokiko/p/12882007.html
Copyright © 2020-2023  润新知