zoukankan      html  css  js  c++  java
  • *query【思维+树状数组】

    题意:

    给定一个 (1 o n) 的全排列,有 (m) 个询问,每次询问求 ([l,r]) 内有多少满足 (lle i<jle r,min(p_i,p_j) = gcd(p_i,p_j))(pair(i,j))
    题目链接:https://nanti.jisuanke.com/t/41391

    分析:

      这题的难点主要是思维的转化。联想用树状数组处理逆序对问题,大体思路和本题差不多。也是在权值上计数,然后按照某一种特定的顺序来放数。
    大体过程:
      先处理出有倍数关系的位置,求出对于一个靠后的位置,有哪些靠前的位置对它有贡献。把查询保存下来,进行离线处理。从前到后遍历位置,对于当前位置 (i) ,把对它有贡献的位置的值加上,然后处理掉以该点为右端点区间查询。

    代码:

    #include<bits/stdc++.h>
    #define pb push_back
    using namespace std;
    typedef pair<int,int> pii;
    const int N=1e5+5;
    int a[N],pos[N],bit[N],n,ans[N];
    vector<pii>q[N];
    vector<int>num[N];
    void add(int x)
    {
        while(x<=n)
        {
            bit[x]++;
            x+=(x&(-x));
        }
    }
    int query(int x)
    {
        int res=0;
        while(x>0)
        {
            res+=bit[x];
            x-=(x&(-x));
        }
        return res;
    }
    int main()
    {
        int m,l,r;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            pos[a[i]]=i;
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&l,&r);
            q[r].pb(make_pair(l,i));
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=a[i]*2;j<=n;j+=a[i])
                num[max(i,pos[j])].pb(min(i,pos[j]));//哪些小位置对哪些大位置有贡献
        }
        for(int i=1;i<=n;i++)//按位置遍历
        {
            for(int j=0;j<num[i].size();j++)
                add(num[i][j]);
            for(int j=0;j<q[i].size();j++)
                ans[q[i][j].second]=query(i)-query(q[i][j].first-1);
        }
        for(int i=1;i<=m;i++)
            printf("%d
    ",ans[i]);
        return 0;
    }
    
    
  • 相关阅读:
    自己动手写动态网站
    CompareValidator控件
    跨数据库服务器查询和跨表更新
    在Windows 2003 IIS 6.0中配置PHP的运行环境(图)
    sql语句跨服务器跨数据库执行
    ASP语法
    web 中 common
    common js
    经典的SQL面试题
    asp:TextBox 的ReadOnly属性 造成后台无法取到值
  • 原文地址:https://www.cnblogs.com/1024-xzx/p/13221844.html
Copyright © 2011-2022 走看看