Use an influence map for target searching. Have a grid and on each node, reserve a spot in a collection of units for each team.
For each unit, generate a collection of coordinates within range and offset these coordinates as the unit moves. When a unit searches for a new target, enumerate over its coordinates within range. If another unit is on one of these coordinates, then that unit is within range.
Check this video out for visualization: https://www.youtube.com/watch?v=MEd6XV2Pecw.
I used this method for attack behaviors between about 1000 objects on 4 teams shown here: https://www.youtube.com/watch?v=y_ewoxlZlgc.
This target searching should be used as a broadphase. Once a target is acquired, range checks should still be done for more accuracy but the overhead for that is so small it's insignificant.