데이터 구조 & 알고리즘 학습 노트: 선분 트 리

  • 단일 업데이트, 구간 구 화 및 구간 구 최대 치
  • #define lson rt<<1, left, m
    #define rson rt<<1|1, m + 1, right
    const int maxn = 1e5+5;
    using namespace std;
    struct Node
    {
        int value;
        int left,right;
        int mid()
        {
            return (left + right) >> 1;
        }
    }node[maxn<<2];
    int lindex[maxn];//              
    void PushUp(int rt)
    {
        node[rt].value = node[rt<<1].value + node[rt<<1|1].value;
        //node[rt].value = max(node[rt<<1].value, node[rt<<1|1].value);
    }
    void BuildTree(int rt, int left, int right)
    {
        node[rt].left = left;
        node[rt].right = right;
        node[rt].value = 0;
        if(left == right)
        {
            scanf("%d",&node[rt].value);
            lindex[left] = rt;
            return ;
        }
        int m = node[rt].mid();
        BuildTree(lson);
        BuildTree(rson);
        PushUp(rt);
    }
    void Update(int rt)
    {
        if(rt == 1)return ;
        int f = rt >> 1;
        int a = node[f<<1].value;
        int b = node[f<<1|1].value;
        node[f].value = a + b;//    
        //node[f].value = max(a,b);//      
        Update(f);
    }
    int ans;
    void Query(int rt, int left, int right)
    {
        if(node[rt].left == left && node[rt].right == right)
        {
            ans += node[rt].value;//    
            //ans = max(ans, node[rt].value);//      
            return ;
        }
        int m = node[rt].mid();
        if(right <= m) Query(rt<<1, left, right);
        else if(left > m) Query(rt<<1|1, left, right);
        else{
            Query(lson);
            Query(rson);
        }
    }

    연습 문제 연습 HDU 1754 (전송 문) I Hate It Time Limit: 9000 / 3000 MS (Java / Others) Memory Limit: 32768 / 32768 K (Java / Others) Problem 많은 학교 에서 비교 하 는 습관 이 유행 하고 있다.선생님 들 은 모모 에서 모모 까지 점수 가 가장 높 은 것 이 얼마 인지 묻 는 것 을 좋아한다.이것 은 많은 학생 들 로 하여 금 매우 반감 을 가지 게 한다.네가 좋아 하 든 안 좋아 하 든 지금 네가 해 야 할 일 은 바로 선생님 의 요구 에 따라 프로그램 을 써 서 선생님 의 질문 을 모 의 하 는 것 이다.물론 선생님 은 어떤 학우 의 성적 을 갱신 해 야 할 때 가 있다.Input 이 문 제 는 여러 그룹 테스트 를 포함 하고 있 습 니 다. 파일 이 끝 날 때 까지 처리 하 십시오.각 테스트 의 첫 줄 에는 두 개의 정수 N 과 M (0 < N < = 20000, 0 < M < 5000) 이 있 는데 각각 학생 의 수량 과 조작 수량 을 대표 한다.학생 ID 번 호 는 각각 1 번 에서 N 번 으로 매 겨 진다.두 번 째 줄 은 N 개의 정 수 를 포함 하고 이 N 명의 학생 들 의 초기 성적 을 대표 하 며 그 중에서 i 의 수 는 ID 가 i 인 학생 들 의 성적 을 대표 한다.다음은 M 줄.줄 마다 하나의 문자 C ('Q' 또는 'U' 만 가 져 오기) 와 두 개의 정수 A, B 가 있 습 니 다.C 가 'Q' 일 때 이것 은 질문 조작 이 라 고 표시 했다. ID 가 A 에서 B (A, B 포함) 까지 의 학생 중에서 성적 이 가장 높 은 것 은 얼마 인지 물 었 다.C 가 'U' 일 때 이것 은 업데이트 작업 이 라 고 표시 하고 ID 가 A 인 학생 의 성적 을 B 로 변경 하 라 고 요구 했다.Output 은 매번 문의 작업 에 대해 한 줄 에서 최고 성적 을 출력 합 니 다.Sample Input 5 6 1 2 3 4 5 Q 1 5 U 3 6 Q 3 4 Q 4 5 U 2 9 Q 1 5 Sample Output 5 6 5 9
    Hint Huge input,the C function scanf() will work better than cin
    #include
    #include
    #define lson rt<<1, left, m
    #define rson rt<<1|1, m + 1, right
    const int maxn = 2e5+5;
    using namespace std;
    struct Node
    {
        int value;
        int left,right;
        int mid()
        {
            return (left + right) >> 1;
        }
    }node[maxn<<2];
    int lindex[maxn];
    void PushUp(int rt)
    {
        node[rt].value = max(node[rt<<1].value, node[rt<<1|1].value);
    }
    void BuildTree(int rt, int left, int right)
    {
        node[rt].left = left;
        node[rt].right = right;
        node[rt].value = 0;
        if(left == right)
        {
            cin>>node[rt].value;
            lindex[left] = rt;
            return ;
        }
        int m = node[rt].mid();
        BuildTree(lson);
        BuildTree(rson);
        PushUp(rt);
    }
    void Update(int rt)
    {
        if(rt == 1)return ;
        int f = rt >> 1;
        int a = node[f<<1].value;
        int b = node[f<<1|1].value;
        node[f].value = max(a,b);
        Update(f);
    }
    int ans;
    void Query(int rt, int left, int right)
    {
        if(node[rt].left == left && node[rt].right == right)
        {
            ans = max(ans, node[rt].value);
            return ;
        }
        int m = node[rt].mid();
        if(right <= m) Query(rt<<1, left, right);
        else if(left > m) Query(rt<<1|1, left, right);
        else{
            Query(lson);
            Query(rson);
        }
    }
    int main()
    {
        ios::sync_with_stdio(false);
        int n, m;
        while(cin>>n>>m)
        {
            BuildTree(1, 1, n);
            while(m--)
            {
                string s;
                int a, b;
                cin>>s>>a>>b;
                if(s[0] == 'Q')
                {
                    ans = 0;
                    Query(1, a, b);
                    cout<else
                {
                    if(s[0] == 'U')
                    {
                        node[lindex[a]].value = b;
                        Update(lindex[a]);
                    }
                }
            }
        }
        return 0;
    }
    

    NYOJ 116 (전송 문) 병사 의 적 을 죽 이 는 시간 제한: 1000 ms | 메모리 제한: 65535 KB 난이도: 5 남장 군 수하 에 N 명의 병사 가 있 는데 각각 1 번 에서 N 번 으로 번 호 를 매 겼 다. 이 병사 들 의 적 을 죽 이 는 수 는 모두 알려 져 있다.
    막노동 자 는 남 장군 수하 의 군사 입 니 다. 남 장군 은 항상 m 번 부터 n 번 까지 병사 의 총 살 적 수 를 알 고 싶 어 합 니 다. 막노동 자 를 도와 남 장군 에 게 대답 해 주세요.
    남 장군 의 한 질문 이후 병사 i 는 또 적 q 명 을 죽 일 수 있 습 니 다. 이후 남 장군 이 다시 물 었 을 때 추가 적 인 적 수 를 고려 해 야 합 니 다.
    입력 한 테스트 데이터 의 첫 줄 은 두 개의 정수 N, M 입 니 다. 그 중에서 N 은 병사 의 개 수 를 표시 합 니 다 (1 < N < 1000000). M 은 명령 의 개 수 를 표시 합 니 다.(1 < M < 100000) 다음 줄 은 N 개의 정수 이 고 ai 는 제 i 호 병사 의 적 을 죽 이 는 수 를 나타 낸다.(0 < = ai < = 100) 다음 M 줄 은 각각 하나의 명령 입 니 다. 이 명령 은 하나의 문자열 과 두 개의 정 수 를 포함 하고 있 습 니 다. 먼저 하나의 문자열 입 니 다. 문자열 QUERY 라면 남 장군 이 조회 작업 을 했 고 뒤의 두 개의 정수 m, n 은 조회 의 시작 과 끝 병사 번 호 를 표시 합 니 다.문자열 ADD 라면 뒤 를 따 르 는 두 정수 I, A (1 < = I < = N, 1 < = A < = 100) 는 제 I 병사 의 신규 살 적 수 를 A 로 표시 합 니 다.각 그룹의 출력 이 한 줄 을 차지 하 는 샘플 입력 5 6 1 2 3 4 5 QUERY 1 3 ADD 1 2 QUERY 1 3 ADD 2 3 QUERY 1 2 QUERY 1 5 샘플 출력 6 8 20
    #include
    #include
    #define lson rt<<1, left, m
    #define rson rt<<1|1, m + 1, right
    const int maxn = 1e6+5;
    using namespace std;
    struct Node
    {
        int value;
        int left,right;
        int mid()
        {
            return (left + right) >> 1;
        }
    }node[maxn<<2];
    int lindex[maxn];
    void PushUp(int rt)
    {
        node[rt].value = node[rt<<1].value + node[rt<<1|1].value;
    }
    void BuildTree(int rt, int left, int right)
    {
        node[rt].left = left;
        node[rt].right = right;
        node[rt].value = 0;
        if(left == right)
        {
            cin>>node[rt].value;
            lindex[left] = rt;
            return ;
        }
        int m = node[rt].mid();
        BuildTree(lson);
        BuildTree(rson);
        PushUp(rt);
    }
    void Update(int rt)
    {
        if(rt == 1)return ;
        int f = rt >> 1;
        int a = node[f<<1].value;
        int b = node[f<<1|1].value;
        node[f].value = a + b;
        Update(f);
    }
    int ans;
    void Query(int rt, int left, int right)
    {
        if(node[rt].left == left && node[rt].right == right)
        {
            ans += node[rt].value;
            return ;
        }
        int m = node[rt].mid();
        if(right <= m) Query(rt<<1, left, right);
        else if(left > m) Query(rt<<1|1, left, right);
        else{
            Query(lson);
            Query(rson);
        }
    }
    int main()
    {
        int n, m;
        ios::sync_with_stdio(false);
        while(cin>>n>>m)
        {
            BuildTree(1, 1, n);
            string s;
            int a, b;
            for(int i = 0; i < m; i++)
            {
                ans = 0;
                string s;
                cin>>s>>a>>b;
                if(s[0] == 'Q'){
                    Query(1, a, b);
                    cout<else{
                    if(s[0] == 'A')
                    {
                        node[lindex[a]].value += b;
                        Update(lindex[a]);
                    }
                }
            }
        }
        return 0;
    }
    

    HDU 1166 (전송 문) 은 상기 제목 과 유사 하 다.
  • 구간 을 수정 하려 면 lazy 표 지 를 사용 해 야 합 니 다. 위 에서 아래로, 하위 구간 을 만나면 수정 이 중단 되 고 아래로 수정 하지 않 습 니 다.다음 에 수정 하면 레이 지 로 고 를 좌우 나무 로 분해 합 니 다.
  • //        【a,b】        c
    #define lson rt<<1, left, m
    #define rson rt<<1|1, m + 1, right
    #define maxn 100004
    using namespace std;
    struct Node{
        int left, right;
        int value;
        int add;//lazy  
        int mid()
        {
            return (left + right) >> 1;
        }
    }node[maxn<<2];
    void PushUp(int rt)
    {
        node[rt].value = node[rt<<1].value + node[rt<<1|1].value;
    }
    void BuildTree(int rt, int left, int right)
    {
        node[rt].left = left;
        node[rt].right = right;
        node[rt].add = 0;
        if(left == right)
        {
            scanf("%d",&node[rt].value);
            return ;
        }
        int m = node[rt].mid();
        BuildTree(lson);
        BuildTree(rson);
        PushUp(rt);
    }
    void PushDown(int rt, int len)//    lazy  
    {//len     
        if(node[rt].add)
        {
            node[rt<<1].add += node[rt].add;
            node[rt<<1|1].add += node[rt].add;
            node[rt<<1].value += node[rt].add * (len - (len >> 1));//len - (len >> 1)         
            node[rt<<1|1].value += node[rt].add * (len >> 1);//len>>1         
            node[rt].add = 0;
        }
    }
    void Update(int rt, int left, int right, int c)
    {
        if(node[rt].left == left && node[rt].right == right)
        {
            node[rt].value += (right - left + 1) * c;
            node[rt].add += c;
            return ;
        }
        PushDown(rt, node[rt].right - node[rt].left + 1);
        int m = node[rt].mid();
        if(right <= m)Update(rt<<1,left,right, c);
        else if(left > m)Update(rt<<1|1,left,right, c);
        else {
            Update(lson, c);
            Update(rson, c);
        }
        PushUp(rt);
    }
    void Query(int rt, int left, int right)
    {
        if(node[rt].left == left && node[rt].right == right)
        {
            ans += node[rt].value;
            return ;
        }
        PushDown(rt, node[rt].right - node[rt].left + 1);
        int m = node[rt].mid();
        if(right <= m) Query(rt<<1,left,right);
        else if(left > m) Query(rt<<1|1,left,right);
        else{
            Query(lson);
            Query(rson);
        }
    }

    연습 문제 Poj 3468 (전송 문) Integers 와 간단 한 문제 시간 제한: 5000 MS 메모리 제한: 131072 K 케이스 시간 제한: 2000 MS 설명
    You have N integers, A1, A2, … , AN. You need to deal with two kinds of operations. One type of operation is to add some given number to each number in a given interval. The other is to ask for the sum of numbers in a given interval.
    Input
    The first line contains two numbers N and Q. 1 ≤ N,Q ≤ 100000. The second line contains N numbers, the initial values of A1, A2, … , AN. -1000000000 ≤ Ai ≤ 1000000000. Each of the next Q lines represents an operation. “C a b c” means adding c to each of Aa, Aa+1, … , Ab. -10000 ≤ c ≤ 10000. “Q a b” means querying the sum of Aa, Aa+1, … , Ab.
    Output
    You need to answer all Q commands in order. One answer in a line.
    Sample Input
    10 5 1 2 3 4 5 6 7 8 9 10 Q 4 4 Q 1 10 Q 2 4 C 3 6 3 Q 2 4 Sample Output
    4 55 9 15 Hint
    The sums may exceed the range of 32-bit integers.
    #include
    #include
    #define lson rt<<1, left, m
    #define rson rt<<1|1, m + 1, right
    #define maxn 100004
    using namespace std;
    struct Node{
        int left, right;
        long long sum;
        long long add;
        int mid()
        {
            return (left + right) >> 1;
        }
    }node[maxn<<2];
    
    void PushUp(int rt)
    {
        node[rt].sum = node[rt<<1].sum + node[rt<<1|1].sum;
    }
    
    void PushDown(int rt, int len)
    {
        if(node[rt].add)
        {
            node[rt<<1].add += node[rt].add;
            node[rt<<1|1].add += node[rt].add;
            node[rt<<1].sum += node[rt].add * (len - (len >> 1));//
            node[rt<<1|1].sum += node[rt].add * (len >> 1);//
            node[rt].add = 0;
        }
    }
    
    void BuildTree(int rt, int left, int right)
    {
        node[rt].left = left;
        node[rt].right = right;
        node[rt].add = 0;
        if(left == right)
        {
            scanf("%I64d",&node[rt].sum);
            return ;
        }
        int m = node[rt].mid();
        BuildTree(lson);
        BuildTree(rson);
        PushUp(rt);
    }
    
    void Update(int rt, int left, int right, long long c)
    {
        if(node[rt].left == left && node[rt].right == right)
        {
            node[rt].sum += (right - left + 1) * c;
            node[rt].add += c;
            return ;
        }
        PushDown(rt, node[rt].right - node[rt].left + 1);
        int m = node[rt].mid();
        if(right <= m)Update(rt<<1,left,right, c);
        else if(left > m)Update(rt<<1|1,left,right, c);
        else {
            Update(lson, c);
            Update(rson, c);
        }
        PushUp(rt);
    }
    
    long long ans;
    void Query(int rt, int left, int right)
    {
        if(node[rt].left == left && node[rt].right == right)
        {
            ans += node[rt].sum;
            return ;
        }
        PushDown(rt, node[rt].right - node[rt].left + 1);
        int m = node[rt].mid();
        if(right <= m) Query(rt<<1,left,right);
        else if(left > m) Query(rt<<1|1,left,right);
        else{
            Query(lson);
            Query(rson);
        }
    }
    int main()
    {
        int n,q;
        while(~scanf("%d%d",&n, &q))
        {
            BuildTree(1,1,n);
            while(q--)
            {
                char s[3];
                int a, b;
                long long c;
                scanf(" %s", s);
                if(s[0] == 'Q')
                {
                    ans = 0;
                    scanf("%d%d",&a,&b);
                    Query(1,a,b);
                    printf("%lld
    "
    ,ans); } else { scanf("%d%d%I64d",&a,&b,&c); Update(1,a,b,c); } } } return 0; }

    좋은 웹페이지 즐겨찾기