zoukankan      html  css  js  c++  java
  • HDU 4777 Rabbit Kingdom

    Rabbit Kingdom

    Time Limit: 3000ms
    Memory Limit: 32768KB
    This problem will be judged on HDU. Original ID: 4777
    64-bit integer IO format: %I64d      Java class name: Main
      Long long ago, there was an ancient rabbit kingdom in the forest. Every rabbit in this kingdom was not cute but totally pugnacious, so the kingdom was in chaos in season and out of season.
      n rabbits were numbered form 1 to n. All rabbits' weight is an integer. For some unknown reason, two rabbits would fight each other if and only if their weight is NOT co-prime.
      Now the king had arranged the n rabbits in a line ordered by their numbers. The king planned to send some rabbits into prison. He wanted to know that, if he sent all rabbits between the i-th one and the j-th one(including the i-th one and the j-th one) into prison, how many rabbits in the prison would not fight with others.
      Please note that a rabbit would not fight with himself.
     

    Input

      The input consists of several test cases.
      The first line of each test case contains two integer n, m, indicating the number of rabbits and the queries.
      The following line contains n integers, and the i-th integer Wi indicates the weight of the i-th rabbit.
      Then m lines follow. Each line represents a query. It contains two integers L and R, meaning the king wanted to ask about the situation that if he sent all rabbits from the L-th one to the R-th one into prison.
      (1 <= n, m, Wi <= 200000, 1 <= L <= R <= n)
      The input ends with n = 0 and m = 0.
     

    Output

      For every query, output one line indicating the answer.
     

    Sample Input

    3 2
    2 1 4
    1 2
    1 3
    6 4
    3 6 1 2 5 3
    1 3
    4 6
    4 4
    2 6
    0 0

    Sample Output

    2
    1
    1
    3
    1
    2

    Hint

      In the second case, the answer of the 4-th query is 2, because only 1 and 5 is co-prime with other numbers in the interval [2,6] .
     

    Source

     
    解题:首先我们需要处理各数距离它左边最近和右边最近的与其不互质的数
    1. $nxt[p]记录最新的含有p因子的数的位置$
    2. $然后分解当前数的因子,就可以找出上个含有p因子的数的位置$
    3. $然后就可以更新上个数的最近的右边不互质数的位置已经当前数左边最近的不互质数的位置$
    接下来就是利用树状数组更新
    1. 对所有左边界为i的数,我们可以把他们对应的位置上加1
    2. 然后对应位置的右边界减去1,因为如果超过右边界,那么对应位置这个数就不应该算进去,所以要减1
    3. 用MS C++交,G++爆内存,奶奶的
     1 #include <iostream>
     2 #include <cstdio>
     3 #include <cstring>
     4 #include <vector>
     5 #include <algorithm>
     6 using namespace std;
     7 const int maxn = 200010;
     8 struct QU {
     9     int L,R,id;
    10     bool operator<(const QU &rhs)const {
    11         return L < rhs.L;
    12     }
    13 } Q[maxn];
    14 int C[maxn],L[maxn],R[maxn],nxt[maxn],d[maxn],ans[maxn],n,m;
    15 vector<int>fac[maxn];
    16 vector<int>Ls[maxn];
    17 void init() {
    18     for(int i = 2; i <= 200000; ++i)
    19         for(int j = i; j <= 200000; j += i)
    20             fac[j].push_back(i);
    21 }
    22 int sum(int i,int ret = 0) {
    23     while(i > 0) {
    24         ret += C[i];
    25         i -= i&-i;
    26     }
    27     return ret;
    28 }
    29 void add(int i,int val) {
    30     while(i <= n) {
    31         C[i] += val;
    32         i += i&-i;
    33     }
    34 }
    35 void solve() {
    36     for(int i = 0; i <= n; ++i) Ls[i].clear();
    37     sort(Q,Q + m);
    38     memset(C,0,sizeof C);
    39     memset(L,0,sizeof L);
    40     memset(R,0,sizeof R);
    41     memset(nxt,0,sizeof nxt);
    42     for(int i = 1; i <= n; ++i) {
    43         for(int j = 0; j < fac[d[i]].size(); ++j) {
    44             int p = fac[d[i]][j];
    45             if(!nxt[p]){
    46                 nxt[p] = i;
    47                 continue;
    48             }
    49             if(!R[nxt[p]]) R[nxt[p]] = i;
    50             if(L[i] < nxt[p]) L[i] = nxt[p];
    51             nxt[p] = i;
    52         }
    53         Ls[L[i]].push_back(i);
    54     }
    55     for(int i = 0,cur = 0; i <= n; ++i){
    56         while(Q[cur].L == i){
    57             ans[Q[cur].id] = sum(Q[cur].R) - sum(Q[cur].L - 1);
    58             ++cur;
    59         }
    60         for(int j = 0; j < Ls[i].size(); ++j){
    61             add(Ls[i][j],1);
    62             if(R[Ls[i][j]]) add(R[Ls[i][j]],-1);
    63         }
    64         if(R[i]) add(R[i],1);
    65     }
    66     for(int i = 0; i < m; ++i)
    67         printf("%d
    ",ans[i]);
    68 }
    69 int main() {
    70     init();
    71     while(scanf("%d%d",&n,&m),n||m) {
    72         for(int i = 1; i <= n; ++i) scanf("%d", d + i);
    73         for(int i = 0; i < m; ++i) {
    74             scanf("%d%d",&Q[i].L,&Q[i].R);
    75             Q[i].id = i;
    76         }
    77         solve();
    78     }
    79     return 0;
    80 }
    View Code
     
     
  • 相关阅读:
    STL容器 erase的使用陷井
    转:VC++线程同步-事件对象
    VC线程同步方法
    C/C++四种退出线程的方法
    rabbitMQ 常用命令
    Spring @Configuration
    Spring RabbitMQ 延迟队列
    rabbitmq web管理界面 用户管理
    Linux下tar.gz 安装
    Linux下RPM软件包的安装及卸载
  • 原文地址:https://www.cnblogs.com/crackpotisback/p/4848654.html
Copyright © 2011-2022 走看看