hdu 1166 적군 포진(나의 첫 번 째 선분 수)

적병 이 포진 하 다
Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 8364    Accepted Submission(s): 3460
Problem Description
C 국 의 앙 숙 A 국 은 그동안 군사훈련 을 하고 있 었 기 때문에 C 국 간첩 두목 인 데 릭 과 그의 수하 인 티 디 는 또 바 빠 지기 시작 했다.A 국 가 는 해안선 을 따라 직선 으로 N 개 공병 캠프 를 배 치 했 는데,데 릭 과 티 디 의 임 무 는 이들 공병 캠프 의 활동 상황 을 감시 하 는 것 이다.어떤 선진 적 인 모니터링 수단 을 취 했 기 때문에 각 공병 캠프 의 인원 C 개국 이 모두 파악 하고 있 는 것 은 명백 하 다.각 공병 캠프 의 인원 은 변동 이 발생 할 수 있 고 몇 명의 인원 이 증가 하거나 감소 할 수 있 지만 이런 것들 은 C 국 의 감 시 를 피 할 수 없다.
중앙정보국 은 적 들 이 도대체 어떤 전술 을 연습 하 는 지 연구 해 야 하기 때문에 Tidy 는 수시로 Derek 에 게 어떤 연속 적 인 공병 캠프 가 모두 몇 명 인지 보고 해 야 한다.예 를 들 어 Derek 은"Tidy,바로 세 번 째 캠프 에서 10 번 째 캠프 까지 모두 몇 명 이 있 는 지 보고 해 야 한다!"라 고 물 었 다.Tidy 는 곧 이 단락 의 총 인원 을 계산 하고 보고 해 야 한다.그러나 적군 캠프 의 인원 이 자주 바 뀌 었 고 Derek 는 매번 질문 하 는 구간 이 다 르 기 때문에 Tidy 는 매번 한 캠프 에 가서 세 어야 했다.곧 지 쳐 버 렸 다.Derek 는 Tidy 의 계산 속도 에 대해 점점 불만 을 가지 게 되 었 다."이 뚱뚱 한 놈 아,계산 이 이렇게 느 리 니 해고 할 게!"Tidy 는'네가 직접 계산 해 봐.이 건 정말 힘 든 일이 야!"나 는 네가 나 를 해고 하 는 것 이 한스럽다!"어 쩔 수 없 이 Tidy 는 컴퓨터 전문가 Windbreaker 에 게 전 화 를 걸 어 구 조 를 요청 할 수 밖 에 없 었 다.Windbreaker 는"뚱 땡 이 야,평소에 acm 문 제 를 많이 풀 고 알고리즘 책 을 많이 보라 고 했 으 니 이제 쓴맛 을 보 았 지?"라 고 말 했다.Tidy:"내 가 잘 못 했 어..."하지만 Windbreaker 는 전 화 를 끊 었 습 니 다.Tidy 는 고민 이 많 습 니 다.이렇게 계산 하면 그 는 정말 무 너 질 것 입 니 다.똑똑 한 독자,당신 은 프로그램 을 써 서 그 를 도와 이 일 을 완성 할 수 있 습 니까?하지만 프로그램 효율 이 높 지 않 으 면 Tidy 는 Derek 의 꾸지람 을 들 을 것 이다.
 
Input
첫 줄 의 정수 T 는 T 조 데이터 가 있 음 을 나타 낸다.
각 조 의 데이터 첫 번 째 줄 의 정수 N(N<=50000)은 적 에 게 N 개의 공병 캠프 가 있 고 그 다음 에 N 개의 정수 가 있 으 며,i 번 째 정수 ai 는 i 번 째 공병 캠프 에서 시작 할 때 ai 개인(1<=ai<=50)이 있다 는 것 을 나타 낸다.
다음 줄 마다 명령 이 있 습 니 다.명령 은 네 가지 형식 이 있 습 니 다.
(1)Add i j,i 와 j 는 정수 로 i 번 째 캠프 에 j 개인 이 증가 하 는 것 을 나타 낸다(j 는 30 을 초과 하지 않 는 다)
(2)Sub i j,i 와 j 는 정수 로 i 번 째 캠프 에서 j 개인(j 가 30 을 초과 하지 않 음)을 감소 하 는 것 을 나타 낸다.
(3)Query i j,i 와 j 는 정수 이 고 i<=j 는 i 에서 j 개 캠프 까지 의 총 인원 을 묻는다.
(4)End 는 끝 을 표시 합 니 다.이 명령 은 각 그룹의 데이터 마지막 에 나타 납 니 다.
각 조 의 데 이 터 는 최대 40000 개의 명령 이 있다.
 
Output
i 조 데이터 에 대해 먼저"Case i:"와 리 턴 을 출력 합 니 다.
각 Query 질문 에 대해 하나의 정 수 를 출력 하고 차 로 돌아 가 는 것 은 문의 구간 의 총 인원 을 나타 내 는데 이 수 는 최대 1000000 을 초과 하지 않 습 니 다.
 
Sample Input

  
1 10 1 2 3 4 5 6 7 8 9 10 Query 1 3 Add 3 6 Query 2 7 Sub 10 2 Add 6 3 Query 3 10 End

 
Sample Output

  
Case 1: 6 33 59

    
제목 의 대의:한 줄 의 수 를 주 고 제목 의 뜻 에 따라 조금씩 증가 하거나 감소 하거나 특정한 구간 의 인원 이 얼마 인지 물 어 볼 것 이다.이 문 제 는 제 가 첫 번 째 로 만난 선분 나무 문제 입 니 다.인상적 입 니 다.저 에 게 주 는 느낌 은 바로 끊임없이 2 분 의 나무 입 니 다.다음은 제 가 쓴 것 입 니 다.
링크:http://acm.hdu.edu.cn/showproblem.php?pid=1166
코드:
#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;

struct node
{
    int left, right, mid;
    int count;
}w[4*50005];

int val[50005];
int sum;

void creat(int a, int b, int r) //  
{
    if(a == b)
    {
        w[r].left = w[r].right = a;
        w[r].count = val[a];
        return;
    }
    w[r].left = a;
    w[r].right = b;
    w[r].mid = (a+b)/2;

    creat(a, w[r].mid, 2*r);
    creat(w[r].mid+1, b, 2*r+1);

    w[r].count = w[2*r].count + w[2*r+1].count;
}

void add(int n, int m, int r)   //  
{
    if(w[r].left == n && w[r].right == n)
    {
        w[r].count += m;
        return;
    }
    if(n > w[r].mid)
    {
        add(n, m, 2*r+1);
        w[r].count = w[2*r].count + w[2*r+1].count;
    }
    else
    {
        add(n, m, 2*r);
        w[r].count = w[2*r].count + w[2*r+1].count;
    }
}

void sub(int n, int m, int r)   //  
{
    if(w[r].left == n && w[r].right == n)
    {
        w[r].count -= m;
        return;
    }
    if(n > w[r].mid)
    {
        sub(n, m, 2*r+1);
        w[r].count = w[2*r].count + w[2*r+1].count;
    }
    else
    {
        sub(n, m, 2*r);
        w[r].count = w[2*r].count + w[2*r+1].count;
    }
}

void query(int a, int b, int r)    //  
{
    if(w[r].left == a && w[r].right == b)
    {
        sum += w[r].count;
    }
    else if(a > w[r].mid)
    {
        query(a, b, 2*r+1);
    }
    else if(b <= w[r].mid)
    {
        query(a, b, 2*r);
    }
    else
    {
        query(a, w[r].mid, 2*r);
        query(w[r].mid+1, b, 2*r+1);
    }
}

int main()
{
    char sh[15];
    int i, t, n, x, y, zz = 1;
    scanf("%d", &t);
    while(t--)
    {
        scanf("%d", &n);
        for(i = 1; i <= n; i++)
        {
            scanf("%d", &val[i]);
        }
        creat(1, n, 1);
        printf("Case %d:
", zz++); while(scanf("%s", sh)) { if(strcmp(sh, "End") == 0) { break; } scanf("%d %d", &x, &y); if(strcmp(sh, "Add") == 0) { add(x, y, 1); } else if(strcmp(sh, "Sub") == 0) { sub(x, y, 1); } else if(strcmp(sh, "Query") == 0) { sum = 0; query(x, y, 1); printf("%d
", sum); } } } return 0; }

좋은 웹페이지 즐겨찾기