Gym101138D Strange Queries 莫队、前缀和、容斥

传送门



THUWC2019D1T1撞题可还行

以前有些人做过还问过我,但是我没有珍惜,直到进入考场才追悔莫及……

设\(que_{i,j}\)表示询问\((1,i,1,j)\)的答案,那么询问\((a,b,c,d)=que_{b,d} - que_{a-1 , d} - que_{b , c - 1} + que_{a - 1 , c - 1}\)

把一个询问拆成\(4\)个询问,然后对这\(4\)个询问莫队就可以了

不知道怎么回事THUWC上想到了莫队想到了前缀和想到了容斥就是没想到莫队+前缀和+容斥……

#include<bits/stdc++.h>
//This code is written by Itst
using namespace std;

inline int read(){
    int a = 0;
    char c = getchar();
    bool f = 0;
    while(!isdigit(c) && c != EOF){
        if(c == ‘-‘)
            f = 1;
        c = getchar();
    }
    if(c == EOF)
        exit(0);
    while(isdigit(c)){
        a = a * 10 + c - 48;
        c = getchar();
    }
    return f ? -a : a;
}

const int MAXN = 5e4 + 3;
int N , M , T , cnt , cntQ;
int arr[MAXN] , times[MAXN][2];
long long ans[MAXN] , cur;
struct query{
    int p1 , p2 , ind , flg;
    query(int a = 0 , int b = 0 , int c = 0 , int d = 0):p1(a) , p2(b) , ind(c) , flg(d){}
    bool operator <(const query b)const{
        return p1 / T == b.p1 / T ? p2 < b.p2 : p1 < b.p1;
    }
}que[MAXN << 2];

inline void add(int a , int ind){
    cur += times[a][ind ^ 1];
    ++times[a][ind];
}

inline void del(int a , int ind){
    cur -= times[a][ind ^ 1];
    --times[a][ind];
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("in","r",stdin);
    freopen("out","w",stdout);
#endif
    N = read();
    T = sqrt(N);
    for(int i = 1 ; i <= N ; ++i)
        arr[i] = read();
    M = read();
    for(int i = 1 ; i <= M ; ++i){
        int a = read() , b = read() , c = read() , d = read();
        que[++cntQ] = query(b , d , i , 1);
        if(a - 1)
            que[++cntQ] = query(a - 1 , d , i , -1);
        if(b - 1)
            que[++cntQ] = query(b , c - 1 , i , -1);
        if(a - 1 && b - 1)
            que[++cntQ] = query(a - 1 , c - 1 , i , 1);
    }
    sort(que + 1 , que + cntQ + 1);
    int l1 = 0 , l2 = 0;
    for(int i = 1 ; i <= cntQ ; ++i){
        while(l1 < que[i].p1)
            add(arr[++l1] , 0);
        while(l1 > que[i].p1)
            del(arr[l1--] , 0);
        while(l2 < que[i].p2)
            add(arr[++l2] , 1);
        while(l2 > que[i].p2)
            del(arr[l2--] , 1);
        ans[que[i].ind] += que[i].flg * cur;
    }
    for(int i = 1 ; i <= M ; ++i)
        cout << ans[i] << ‘\n‘;
    return 0;
}

原文地址:https://www.cnblogs.com/Itst/p/10320391.html

时间: 2024-07-30 12:52:44

Gym101138D Strange Queries 莫队、前缀和、容斥的相关文章

CodeForces - 617E XOR and Favorite Number (莫队+前缀和)

Bob has a favorite number k and ai of length n. Now he asks you to answer m queries. Each query is given by a pair li and ri and asks you to count the number of pairs of integers i and j, such that l ≤ i ≤ j ≤ r and the xor of the numbers ai, ai + 1,

CodeForces 375D Tree and Queries 莫队||DFS序

Tree and Queries 题意:有一颗以1号节点为根的树,每一个节点有一个自己的颜色,求出节点v的子数上颜色出现次数>=k的颜色种类. 题解:使用莫队处理这个问题,将树转变成DFS序区间,然后就是开一个数据记录下出现次数为k次的颜色数目,查询的时候直接返回这个数组中的对应的值就行了. 注意的就是记得将节点的颜色传递给dfs序对应位置的颜色. 这个忘记了找了好久的bug. 代码: 1 #include<bits/stdc++.h> 2 using namespace std; 3

[Codeforces375D]Tree and Queries(莫队算法)

题意:给定一棵树,每个节点有颜色,对于每个询问(u,k)询问以u为根节点的子树下有多少种颜色出现次数>=k 因为是子树,跟dfs序有关,转化为一段区间,可以用莫队算法求解 直接用一个数组统计出现次数>=k的颜色 Code #include <cstdio> #include <algorithm> #include <cmath> #define N 100010 using namespace std; int n,m,A[N],bl[N],Ans[N],

Jzzhu and Numbers CodeForces - 449D (高维前缀和,容斥)

大意: 给定集合a, 求a的按位与和等于0的非空子集数. 首先由容斥可以得到 $ans = \sum \limits_{0\le x <2^{20}} (-1)^{\alpha} f_x$, 其中$\alpha$为$x$二进制中$1$的个数, $f_x$表示与和等于$x$的非空子集数. $f_x$是一个$20$维前缀和, 按传统容斥做法的话显然要超时, 可以每次求一维的和, 再累加 比方说对于2维前缀和, 用容斥的求法是这样 for (int i=1; i<=n; ++i) { for (in

Codeforces 838A - Binary Blocks(二维前缀和+容斥)

838A - Binary Blocks 思路:求一下前缀和,然后就能很快算出每一小正方块中1的个数了,0的个数等于k*k减去1的个数,两个的最小值就是要加进答案的值. 代码: #include<bits/stdc++.h> using namespace std; #define ll long long #define pb push_back #define mem(a,b) memset((a),(b),sizeof(a)) const int INF=0x3f3f3f3f; cons

JZYZOJ1518 [haoi2011]b 莫比乌斯反演 分块 容斥

http://172.20.6.3/Problem_Show.asp?id=1518最开始只想到了n^2的写法,肯定要超时的,所以要对求gcd的过程进行优化.首先是前缀和容斥,很好理解.第二个优化大致如下:u为莫比乌斯函数,t为gcd(x,y)为i的倍数的数的个数:满足gcd(x,y)=1的数字对的数量=sigma(1<=i<=min(x,y))u[i]*t[i];t[i]=(x/i)*(y-i);由小数向下取整可知有连续的i满足x/i为定值,y/i也是定值,所以可以分块计算,用u[i]的前缀

Codeforces Round #340 (Div. 2) E. XOR and Favorite Number 【莫队算法 + 异或和前缀和的巧妙】

任意门:http://codeforces.com/problemset/problem/617/E E. XOR and Favorite Number time limit per test 4 seconds memory limit per test 256 megabytes input standard input output standard output Bob has a favorite number k and ai of length n. Now he asks yo

LightOJ 1188 Fast Queries(简单莫队)

1188 - Fast Queries    PDF (English) Statistics Forum Time Limit: 3 second(s) Memory Limit: 64 MB Given an array of N integers indexed from 1 to N, and q queries, each in the form i j, you have to find the number of distinct integers from index i to 

Codeforces 375D Tree and Queries(DFS序+莫队+树状数组)

题目链接  Tree and Queries 题目大意  给出一棵树和每个节点的颜色.每次询问vj, kj 你需要回答在以vj为根的子树中满足条件的的颜色数目, 条件:具有该颜色的节点数量至少为kj. (莫队居然可以过) 首先转DFS序,这样就变成了区间查询. 然后直接套用莫队,求出每次询问状态下的t[],t[k]表示当前区间内拥有k个节点的颜色数量. 然后统计t[k] + t[k + 1], ..., t[MAX]即可,这个过程用树状数组维护. #include <bits/stdc++.h>