문제 풀이 [luoguP 4145 하나님 이 문 제 를 만 드 신 7 분 2 (화신 이 각국 을 돌아 다 니 며)]

6387 단어 해제선분 수
제목 링크
문제 풀이
구간 의 개방 과 구 조 를 지원 하 는 서열
알고리즘: 선분 트 리 는 개방 측 수정 과 구간 구 화 를 실현 합 니 다.
분석:
  • 분명히 이 문제 의 구 와 조작 은 선분 트 리 로 유지 할 수 있다
  • 그런데 어떻게 구간 개방 을 실현 합 니까
  • 여러분 은 이런 경험 이 있 습 니까? 계산 기 를 할 때 한 개 수 를 미 친 듯 이 누 르 면 결국은 1 이 되 고 그 다음 에 어떻게 시작 하 든 1 (1 – √ = 1 = 1)
  • 똑 같은, 0 – √ = 0 = 0
  • 따라서 한 구간 의 모든 수 ≤ 1 ≤ 1 만 있 으 면 수정 하지 않 아 도 된다
  • 실현:
  • 선분 수 유지 구간 과 sum s u m 와 최대 치 Max M a x
  • 수정 과정 에서 Max > 1Ma x > 1 구간 만 수정
  • 잎 노드 에 이 르 러 sum s u m 와 Max M a x 를 처방 하면 됩 니 다
  • 복잡 도:
  • 매개 수 ≤ 1012 ≤ 10 12, 그러므로 많아야 6 회 처방 하면 1
  • 을 얻 을 수 있다.
  • 매번 조작 은 logn log ⁡ n 이 고 전체 복잡 도 O (nlogn) O (n log ⁡ n)
  • 주의사항:
  • long long
  • 을 사용 하 세 요
  • 이 가능 하 다, ~ 할 수 있다,...
    코드:
    #include 
    #include 
    #include 
    #include 
    
    using namespace std;
    typedef long long LL;
    const int MAXN = 100100;
    
    int n, m;
    int cnt;
    LL a[MAXN];
    struct node
    {
        int left, right;
        LL s, Max;
        node *ch[2];
    }pool[MAXN << 2], *root;
    
    inline void pushup(node *r)
    {
        r->s = r->ch[0]->s + r->ch[1]->s;
        r->Max = max(r->ch[0]->Max, r->ch[1]->Max);
    }
    
    inline void Build_Tree(node *r, int left, int right)
    {
        r->left = left;
        r->right = right;
        if(left == right)
        {
            r->s = r->Max = a[left];
            return ;
        }
        int mid = (left + right) / 2;
        node *lson = &pool[++cnt];
        node *rson = &pool[++cnt];
        r->ch[0] = lson;
        r->ch[1] = rson;
        Build_Tree(lson, left, mid);
        Build_Tree(rson, mid + 1, right);
        pushup(r);
    }
    
    inline void change(node *r, int left, int right)
    {
        if(r->left == r->right)
        {
            r->s = sqrt(r->s);
            r->Max = sqrt(r->Max);
            return ;
        }
    
        int mid = (r->left +r-> right) / 2;
        if(left <= mid && r->ch[0]->Max > 1) change(r->ch[0], left, right);
        if(mid < right && r->ch[1]->Max > 1) change(r->ch[1], left, right);
        pushup(r);
    }
    
    inline LL query(node *r, int left, int right)
    {
        if(r->left == left && r->right == right)
            return r->s;
        if(r->ch[0]->right >= right) return query(r->ch[0], left, right);
        else if(r->ch[1]->left <= left) return query(r->ch[1], left, right);
        else
            return query(r->ch[0], left, r->ch[0]->right) + 
                   query(r->ch[1], r->ch[1]->left, right);
    }
    int main()
    {
        scanf("%d", &n);
        root = &pool[0];
        for(int i = 1; i <= n; i++) scanf("%lld", &a[i]);
        scanf("%d", &m);
        Build_Tree(root, 1, n);
        for(int i = 1; i <= m; i++)
        {
            int opt, l, r;
            scanf("%d%d%d", &opt, &l, &r);
            if(l > r) swap(l, r);
            if(opt) printf("%lld
    "
    , query(root, l, r)); else change(root, l, r); } return 0; }
  • 좋은 웹페이지 즐겨찾기