query 2019徐州网络赛(树状数组)

query

\[
Time Limit: 2000 ms \quad Memory Limit: 262144 kB
\]

题意

补题才发现比赛的时候读了一个假题意....
给出长度为 \(n\) 的排列,在给出 \(m\) 次询问,每次询问有一对 \(l、r\),问满足 \(min(ai, aj) = gcd(ai, aj)\) 的 \(pair(i, j)\) 对数。

思路

考虑离线做
先把每个数出现的位置记录下来,然后预处理出所有的 \(pair\)。
对于一个数字 \(x\),其满足条件的另一个数有 \(\sum_{k=2}^{\lfloor\frac{n}{x}\rfloor}kx\),那么就可以预处理每一个 \(x\),找出所有的 \(kx\),记录 \(x\) 和 \(kx\) 的位置,就是一对 \(pair\)。
保存一对 \(pair\) 时,将信息保存在较右的位置上。
那么我们就可以每次更新一个位置,更新时候将以这个位置为右端点的所有左端点释放出来,表示存在一个答案。
然后边更新边查询,当某个询问的右端点正好是我现在刚刚更新完的点时,由于已经更新出来的所有 \(pair\) 的右端点都在询问的 \(r\) 左侧,那么只要保证这些 \(pair\) 的左端点都在询问的 \(l\) 右侧就可以,那么我就可以更新 \(pair\) 的时候,更新在左侧,然后用树状数组来查询区间内的和。

/***************************************************************
    > File Name    : a.cpp
    > Author       : Jiaaaaaaaqi
    > Created Time : Mon 09 Sep 2019 11:49:25 PM CST
 ***************************************************************/

#include <map>
#include <set>
#include <list>
#include <ctime>
#include <cmath>
#include <stack>
#include <queue>
#include <cfloat>
#include <string>
#include <vector>
#include <cstdio>
#include <bitset>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <unordered_map>
#define  lowbit(x)  x & (-x)
#define  mes(a, b)  memset(a, b, sizeof a)
#define  fi         first
#define  se         second
#define  pb         push_back
#define  pii        pair<int, int>

typedef unsigned long long int ull;
typedef long long int ll;
const int    maxn = 1e5 + 10;
const int    maxm = 1e5 + 10;
const ll     mod  = 1e9 + 7;
const ll     INF  = 1e18 + 100;
const int    inf  = 0x3f3f3f3f;
const double pi   = acos(-1.0);
const double eps  = 1e-8;
using namespace std;

int n, m;
int cas, tol, T;

struct Node {
    int l, r, id;
    bool operator < (Node a) const {
        return r<a.r;
    }
} node[maxn];
int a[maxn], p[maxn];
int ans[maxn];
vector<int> vv[maxn];

int sum[maxn];

void update(int p) {
    for(int i=p; i<=n; i+=lowbit(i)) {
        sum[i] ++;
    }
}

int query(int p) {
    int ans = 0;
    for(int i=p; i>=1; i-=lowbit(i)) {
        ans += sum[i];
    }
    return ans;
}

int main() {
    // freopen("in", "r", stdin);
    scanf("%d%d", &n, &m);
    for(int i=1; i<=n; i++) {
        scanf("%d", &a[i]);
        p[a[i]] = i;
        vv[i].clear();
    }
    for(int i=1; i<=n; i++) {
        for(int j=i+i; j<=n; j+=i) {
            vv[max(p[i], p[j])].pb(min(p[i], p[j]));
        }
    }
    for(int i=1; i<=m; i++) {
        scanf("%d%d", &node[i].l, &node[i].r);
        node[i].id = i;
    }
    sort(node+1, node+1+m);
    int ask = 1;
    for(int i=1; i<=n; i++) {
        if(ask > m) break;
        for(auto j : vv[i]) update(j);
        while(ask<=m && node[ask].r == i) {
            ans[node[ask].id] = query(i) - query(node[ask].l-1);
            ask++;
        }
    }
    for(int i=1; i<=m; i++) {
        printf("%d\n", ans[i]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/11495145.html

时间: 2024-11-09 23:11:30

query 2019徐州网络赛(树状数组)的相关文章

Ryuji doesn&#39;t want to study 2018徐州icpc网络赛 树状数组

Ryuji is not a good student, and he doesn't want to study. But there are n books he should learn, each book has its knowledge a[i]a[i]. Unfortunately, the longer he learns, the fewer he gets. That means, if he reads books from ll to rr, he will get a

2019徐州网络赛 XKC&#39;s basketball team 线段树

网址:https://nanti.jisuanke.com/t/41387 题意: 大家好,我是训练时长两年半的个人练习生蔡徐坤,我的爱好是唱,跳,rap,篮球. 给出一段长度为$n,(n \leq 1e5)$的序列,对每一个数,求出它和它后面比它大$m$的数中间夹着的数的数量,没有输出$-1$. 题解: 直接建线段树,维护最大值,然后查询时对第$i$个数,搜索区间$[i,n]$之中大于$num[i]+m$的值的位置的最大值,具体操作是先限定区间,然后求出所有合法位置,取最大值,如果搜索不到则返

2019徐州网络赛

I 题 query 题目链接 题目大意是给一个N(<=1e5) permutation  p (下标从1开始) , 现在定义一种pair( i ,j) ,其满足 min(pi?,pj?)=gcd(pi?,pj?),现在有M (<=1e5) 组区间查询[l,r]询问 满足 l <= i < j <= r 的pair有多少对. 这是一种偏序关系的问题,看了一点CDQ 解偏序的介绍 , 感觉也可以树状数组来搞.预处理出每个符合要求的点对( l , r )位置,在一维树状数组上修改点

2019徐州网络赛 I J M

I. query 比赛时候没有预处理因子疯狂t,其实预处理出来因子是\(O(nlog(n))\)级别的 每个数和他的因子是一对偏序关系,因此询问转化为(l,r)区间每个数的因子在区间(l,r)的个数 预处理出来每个位置上的数所有因子的位置,用可持久化线段树维护,区间询问 #include<bits/stdc++.h> #define ll long long #define mk make_pair #define ft first #define se second #define pii

【2019.09.07】2019徐州网络赛

补题地址:https://www.jisuanke.com/contest/3005?view=challenges 题目: A:? B:? C:? D:? E:? F: G:? 回文树+二进制统计回文串内不同字母数技巧https://blog.csdn.net/Cassie_zkq/article/details/100606270 H: I:? J: K:? L: M:? 原文地址:https://www.cnblogs.com/ncu2019/p/11482910.html

2019 徐州网络赛 center

题意:n个点,求最小加上几个点让所有点关于一个点(不需要是点集里面的点)中心对称 题解:双重循环枚举,把中点记录一下,结果是n-最大的中点 1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long ll; 4 typedef unsigned long long ull; 5 #define mem(s) memset(s, 0, sizeof(s)) 6 const int INF = 0x3f3f3f3f;

2019徐州网络赛 H.function

题意: 先有\(n=p_1^{k_1}p_2^{k_2}\cdots p_m^{k_m}\),定义\(f(n)=k_1+k_2+\cdots+k_m\). 现在计算 \[ \sum_{i=1}^nf(i!)\% 998244353 \] 思路: 首先注意到\(f\)函数有这样一个性质:\(f(ab)=f(a)+f(b)\). 那么我们化简所求式子有: \[ \begin{aligned} &\sum_{i=1}^nf(i!)\=&\sum_{i=1}^n\sum_{j=1}^if(j)\=

PAT甲题题解-1095. Cars on Campus(30)-(map+树状数组,或者模拟)

题意:给出n个车辆进出校园的记录,以及k个时间点,让你回答每个时间点校园内的车辆数,最后输出在校园内停留的总时间最长的车牌号和停留时间,如果不止一个,车牌号按字典序输出. 几个注意点: 1.如果一个车连续多次进入,只取最后一个 2.如果一个车连续多次出去,只取第一个 3.一个车可能出入校园内好几次,停留时间取总和 实际上题目就是让我们求某个时间段内的车辆总和,时间段其实就相当于一个区间,区间求和的话,很快就联想到树状数组和线段树.然而怎么将时间段和区间联系起来呢,那就存储出现在记录和询问里的所有

[hdu 5032]2014北京网络赛Always Cook Mushroom 离散化+离线线段树/树状数组

Always Cook Mushroom Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 196    Accepted Submission(s): 54 Problem Description Matt has a company, Always Cook Mushroom (ACM), which produces high-q