Replace a row in a dataframe with two new rows derived from the former

Here is a suggestion how you could do it:

library(dplyr)

df %>% 
  mutate(id = row_number()) %>%                         # ad row id
  filter(y1 < 0 & y2 > 0) %>%                           # filter by condition
  slice(rep(1:n(), each = 2)) %>%                       # duplicate each row
  group_by(id) %>%                                      # group by id
  mutate(x2 = ifelse(row_number()==1, x2-x1, x2),       # some ifelse for the condtions
         y2 = ifelse(row_number()==1, 0,y2)) %>% 
  mutate(x1 = ifelse(row_number()==2, lag(x2), x1), 
         y1 = ifelse(row_number()==2, lag(y2), y1)) %>% 
  bind_rows(df %>% mutate(id = row_number())) %>%       # bind with original df by adding again id
  arrange(id) %>%                                       # arrang id
  slice(-3) %>%                                         # remove the third of each group
  ungroup()
     x1    x2    y1    y2     p    id
  <dbl> <dbl> <dbl> <dbl> <dbl> <int>
1     0   100   -20   -10  0.1      1
2   100   150   -10     0  0.2      2
3   150   250     0    20  0.2      2
4   250   500    20    40  0.08     3
5   500  1000    40    60  0.04     4
6  1000    NA    60    NA NA        5