• 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 )位置,在一维树状数组上修改点对右端位置 r 的值(+1),这些点对排序好后放在gcdp(这些点对的数量是 NlogN级别的)。
    然后离线做,存查询对,并排序。按顺序回答查询,如果查询为 [L,R] 就可以二分查找[L,L] 在 gcdp里的位置 ind,然后将gcdp里 ind 位置前 所有的点对 对树状数组的修改还原(-1),再通过树状数组查询 R 的前缀和 ,即是当前查询的答案。(因为这样可以满足树状数组里 [1,R]全部都是  l >= L 的点对施加的影响 , l < L 的点对影响必然在ind位置之前所以被还原了),这是看CDQ偏序得到的想法 。
    因为查询是排好序的,所以每一个点对(l , r)给树状数组的影响最多只有两次(+1 与 -1),只要记录上一次ind的位置就可以不重复-1,最坏复杂度 O(2*N*logN*logN + M * log(N*logN) )

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 typedef pair<int,int> pii;
     5 const int maxn = 1e5;
     6 int n,m;
     7 int raw[maxn + 10],ind[maxn + 10];
     8 vector<pii> gcdp;
     9 pii query[maxn+10];
    10 int queryp[maxn + 10];
    11 int ans[maxn + 10];
    12 int Flick[maxn + 10];
    13 
    14 bool cmp(int i,int j){
    15     return query[i] < query[j];
    16 }
    17 
    18 int lowbit(int x){
    19     return x&(-x);
    20 }
    21 
    22 void FlickUpdate(int ind,int val){
    23     while(ind <= n){
    24         Flick[ind] += val;
    25         ind += lowbit(ind);
    26     }
    27 }
    28 
    29 int FlickQuery(int ind){
    30     int ret = 0;
    31     while(ind > 0){
    32         ret += Flick[ind];
    33         ind -= lowbit(ind);
    34     }
    35     return ret;
    36 }
    37 
    38 int main(){
    39     //__clock_t stt = clock();
    40     scanf("%d%d",&n,&m);
    41     for(int i=1;i<=n;++i){
    42         scanf("%d",&raw[i]);
    43         ind[raw[i]] = i;
    44     }
    45 //    int tot = 0;
    46     for(int i=1;i<=n;++i){
    47         for(int j = 2 * i;j<=n; j+= i){
    48             int L = ind[i] , R = ind[j];
    49             if(L >= R) swap(L,R);
    50             gcdp.emplace_back(make_pair(L,R));
    51         }
    52     }
    53     sort(gcdp.begin(),gcdp.end());
    54 //    puts("gcdmin pair :");
    55 //    for(auto item : gcdp) printf("%d %d
    ",item.first
    56 //        ,item.second);
    57 //    puts("");
    58     for(auto item : gcdp){
    59         int tmp = item.second;
    60 //        printf("second : %d
    ",tmp);
    61         FlickUpdate(tmp,1);
    62     }
    63 
    64     for (int j = 1; j <= m; ++j) {
    65         int l,r;
    66         scanf("%d%d",&l,&r);
    67         query[j] = make_pair(l,r);
    68         queryp[j] = j;
    69     }
    70     sort(queryp + 1 ,queryp + 1 + m,cmp);
    71 //    puts("query pair :");
    72 //    for(int j = 1;j<=m;++j) printf("%d %d
    ",query[queryp[j]].first
    73 //                ,query[queryp[j]].second);
    74 //    puts("");
    75     int last = 0;
    76     for(int j=1;j<=m;++j){
    77         int numq = queryp[j];
    78         pii qry = query[numq];
    79 
    80         pii change = make_pair(qry.first,qry.first);
    81         int bound = lower_bound(gcdp.begin(),gcdp.end(),change) - gcdp.begin();
    82 //        printf("[%d,%d] : %d %d
    ",qry.first,qry.second,last,bound);
    83         for(int k = last;k<bound ;++k){
    84             FlickUpdate(gcdp[k].second,-1);
    85         }
    86         last = max(bound,last);
    87 
    88         ans[numq] = FlickQuery(qry.second);
    89     }
    90     for(int j=1;j<=m;++j){
    91         printf("%d
    ",ans[j]);
    92     }
    93     //__clock_t edt = clock();
    94 //    printf("Used Time : %.3lfms
    ", static_cast<double>(edt - stt)/1000.0);
    95     return 0;
    96 }
    View Code

     开始gcdp的数组大小开少了会RE,后来改用vector ;最初没有记录上一次 ind 的位置导致重复-1,样例太水,还是自己构造的数据发现的。

    如果是解多维或者其他大小的偏序关系区间查询问题,如果查询没有强制在线,应该都可以转化成这种离线存查询排序,以最后一维度值做树状数组的查询与修改。而这种做法需要小心每个点的修改次数。

    ps:此题还有CDQ与线段树做法。

  • 相关阅读:
    ios开发学习视图切换(View Transition)效果源码分享系列教程
    ios开发学习cocos2d(cocos2d)效果源码分享系列教程
    C++类模板定义放在cpp里报错:LNK2019无法解析的外部符号
    std::string学习
    C++之ODB框架
    C++虚析构函数
    Windows编译GRPC
    Qt信号与槽原理
    GRPC环境配置
    C++传入指针并在内部new失败
  • 原文地址:https://www.cnblogs.com/Kiritsugu/p/11493247.html
Copyright © 2020-2023  润新知