Блог пользователя TuanGe

Автор TuanGe, история, 3 года назад, По-английски

Meet a problem, but can't find solutions on internet. I know here are smartest people, so hope can get some help.

The problem is, starting from 0 degree, we rotate theta every time, theta is a floating point, like 33.7 degree. So now we have an array of angle with length of n, r = [0, theta, 2*theta, ..., (n-1)*theta] (wrap to [0..2*PI]).

And we are given an start index a and end index b, how can we quickly find all indices in [a..b] whose angle fall into angel range [t1..t2] (the blue area)? There could be many queries.

Really thanks for any idea, I can only think out iterating all indices one by one.

  • Проголосовать: нравится
  • +7
  • Проголосовать: не нравится

»
3 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Auto comment: topic has been updated by TuanGe (previous revision, new revision, compare).

»
3 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

Auto comment: topic has been updated by TuanGe (previous revision, new revision, compare).

»
3 года назад, # |
  Проголосовать: нравится 0 Проголосовать: не нравится

I just realize I can use sqrt decomposition. Divide r into $$$\sqrt{n}$$$ parts, and sort all elements in one part.

  • »
    »
    3 года назад, # ^ |
      Проголосовать: нравится +3 Проголосовать: не нравится

    Or just sort indexes by i*theta%2pi and answer linear to answer length.

    • »
      »
      »
      3 года назад, # ^ |
        Проголосовать: нравится 0 Проголосовать: не нравится

      Yes, should mod 2*pi, forget to mention

      • »
        »
        »
        »
        3 года назад, # ^ |
          Проголосовать: нравится +3 Проголосовать: не нравится

        You can just sort all elements in this way. Than find ‘a’ by binary search and collect everything up to ‘b’.

        • »
          »
          »
          »
          »
          3 года назад, # ^ |
          Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

          Wait, if we sort all elements by i*theta%2pi, then the index from a to b is not continuous. And we also can't find a using binary search.

          • »
            »
            »
            »
            »
            »
            3 года назад, # ^ |
              Проголосовать: нравится 0 Проголосовать: не нравится

            You preserve index-value relation with pairs or map, or any other way:

            N = 8, theta = 0.6pi, arr = [0, 06.pi, 1.2pi, 1.8pi, 2.4pi, 3.0pi, 3.6pi, 4.2pi]

            After pairs sort: [(0.0, 0), (0.2pi, 7), (0.4pi, 4), (0.6pi,1), (pi, 5), (1.2pi, 2), (1.6pi, 6), (1.8pi,3)]. Pair.second is initial index. Now can you can do binary search.

            • »
              »
              »
              »
              »
              »
              »
              3 года назад, # ^ |
                Проголосовать: нравится 0 Проголосовать: не нравится

              Yes, but there is also an index constraint. We want to find indices in [a..b]

              • »
                »
                »
                »
                »
                »
                »
                »
                3 года назад, # ^ |
                Rev. 2   Проголосовать: нравится +3 Проголосовать: не нравится

                Ah, now I got it. We have two coordinates here. Well, we could think of treap (cartesian tree) here… But since we need every index, and not their count, we also could still stick up to sorting :) with same complexity. Initial one, given in problem (but maybe with angles mod’ed ti 2pi). When you are on angle arr[a] and want to get to sector-t1-t2, you know you should jump either ((2pi + t1 — arr[a])%2pi(to make sure its positive)/theta; or to next index after it. So you can find a, calc step to angle-t1, jump to that index, take all (or one, or none) indexes before angle-t2, than calc-and-jump to t1 again, until you reach index b. Thought treap will performe better if t2-t1 is less then theta.

                • »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  »
                  3 года назад, # ^ |
                  Rev. 2   Проголосовать: нравится 0 Проголосовать: не нравится

                  Thanks for discussing!

                  Not sure how to use treap here. But I should mention the value in problem. t2-t1=0.05, theta=3.73, both in radian. And it is floating points, so it is a little hard to decide how to jump....

»
3 года назад, # |
  Проголосовать: нравится +3 Проголосовать: не нравится

I would like to know what the constraints are but assuming n is up to like 1e6, what we could do is take the modulo of the angles and use coordinate compression on them. After that, we could use a persistent segtree to the answer from 1 to b and subtract it from the answer from 1 to a-1

  • »
    »
    3 года назад, # ^ |
      Проголосовать: нравится 0 Проголосовать: не нравится

    Actually it is not an algorithm problem, but n can be very large, about 1e7.
    Sorry can you explain a little more? So what information we should store in leaf? And since we need a list of indices, I think it will be expensive to remove indices [1..a-1] from [1..b]

    • »
      »
      »
      3 года назад, # ^ |
        Проголосовать: нравится +6 Проголосовать: не нравится

      First, please be more specific about the problem or link the place you found it. If you actually need a list of all the indices it would be O(n) per query to get that anyways so the optimal solution would be iterating through the indices. We have no way of knowing the restrictions of the problem that could make the problem more interesting because you're transcribing very limited information.

      But about what you asked, i was thinking the problem was about getting the size of the answer. In each leaf there would be the ammount of indices with that angle value and since a persistent segtree can store all the versions of itself it would be possible to get it in O(logn).

      • »
        »
        »
        »
        3 года назад, # ^ |
          Проголосовать: нравится 0 Проголосовать: не нравится

        Thanks for discussing and sharing your idea about segemnt tree! This problem is a simplified version that I meet in work.

        For the original problem, if you are interested, I can describe that (actually not so important). For fibonacci lattice on a sphere, I want to find all point indices in an area (theta_lo <= theta <= theta_hi, phi_lo <= phi <= phi_hi).

        And I just realize I can divide all these angles into $$$\sqrt{n}$$$ blocks, and sort all indices by their angles % 2pi. Then for a query [a..b], if part of it fall in some block, then I can use binary search to find start and end position, and get all elements in that range. In this way I don't need to iterate all indices between [a..b].