선분 수 - hdu 1166 적군 포진

1. 제목 회고
제목 링크: 적군 포진
Problem Description
C 국 의 앙 숙 A 국 은 그동안 군사훈련 을 하고 있 었 기 때문에 C 국 간첩 두목 인 데 릭 과 그의 수하 인 티 디 는 또 바 빠 지기 시작 했다.A 국 가 는 해안선 을 따라 직선 으로 N 개 공병 캠프 를 배 치 했 는데, 데 릭 과 티 디 의 임 무 는 이들 공병 캠프 의 활동 상황 을 감시 하 는 것 이다.어떤 선진 적 인 모니터링 수단 을 취 했 기 때문에 각 공병 캠프 의 인원 C 개국 이 모두 파악 하고 있 는 것 은 명백 하 다. 각 공병 캠프 의 인원 은 변동 이 발생 할 수 있 고 몇 명의 인원 이 증가 하거나 감소 할 수 있 지만 이런 것들 은 C 국 의 감 시 를 피 할 수 없다.
중앙정보국 은 적 들 이 어떤 전술 을 연습 하 는 지 연구 해 야 하기 때문에 티 디 는 데 릭 에 게 연속 적 인 공병 캠프 가 모두 몇 명 인지 수시로 보고 해 야 한다. 예 를 들 어 데 릭 은 "티 디, 세 번 째 캠프 에서 10 번 째 캠프 까지 모두 몇 명 인지 즉시 보고 해 야 한다" 고 물 었 다. 티 디 는 곧 이 구간 의 총 인원 을 계산 하고 보고 해 야 한다.그러나 적군 캠프 의 인원 이 자주 바 뀌 었 고 Derek 는 매번 질문 하 는 구간 이 다 르 기 때문에 Tidy 는 매번 한 캠프 에 가서 세 어야 했다. 곧 지 쳐 버 렸 다. Derek 는 Tidy 의 계산 속도 에 대해 점점 불만 을 가지 게 되 었 다. "이 뚱뚱 한 놈 아, 계산 이 이렇게 느 려. 내 가 너 를 해고 할 게!" Tidy 는 생각 했다."네가 직접 계산 해 봐. 이 건 정말 힘 든 일이 야. 나 는 네가 나 를 해고 하 는 것 이 한스러워!" 어 쩔 수 없 이 티 디 는 컴퓨터 전문가 인 윈 드 브 레이 커 에 게 전 화 를 걸 어 구 조 를 구 할 수 밖 에 없 었 다. 윈 드 브 레이 커 는 "뚱 땡 이 야. 평소에 acm 문 제 를 많이 풀 고 알고리즘 책 을 많이 보라 고 했 어. 이제 쓴맛 을 봤 지?" 라 고 말 했다. 티 디 는 "내 가 잘 못 했 어." 라 고 말 했다."하지만 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 문의 에 대해 하나의 정 수 를 출력 하고 차 로 돌아 가 문의 구간 의 총 인원 을 표시 합 니 다. 이 수 는 int 이내 에 있 습 니 다.
 
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. 문제 풀이 사고
이 문 제 는 바로 선분 나무 가 '구간 구 화' 방면 에서 의 응용 이다.
온라인 트 리 지식 점 블 로그 에서 우 리 는 선분 트 리 구축, 구간 조회 및 단일 노드 업데이트 또는 구간 업데이트 에 대해 이야기 했다.
이 문 제 는 주로 단일 노드 의 업데이트 입 니 다. 원 블 로그 의 템 플 릿 을 간단하게 수정 하면 본 문제 에 사용 할 템 플 릿 (구간 과) 을 얻 을 수 있 습 니 다.
const int maxn = 150005;

struct SegTreeNode
{
    int val;
}segTree[maxn]; 		//     

void build(int root, int arr[], int istart, int iend)
{
    if(istart == iend)					//    
        segTree[root].val = arr[istart];
    else{
        int mid = (istart + iend) / 2;
        build(root*2, arr, istart, mid);//       
        build(root*2+1, arr, mid+1, iend);//       
   		segTree[root].val = segTree[root*2].val + segTree[root*2+1].val; 
    }
}
 
int query(int root, int nstart, int nend, int qstart, int qend)
{
    //                
    if(qstart <= nstart && qend >= nend)
        return segTree[root].val;
    int mid = (nstart + nend) / 2;
 	int ans = 0;
 	if(qstart<=mid)	ans += query(root*2, nstart, mid, qstart, qend);
 	if(qend>mid)	ans += query(root*2+1, mid + 1, nend, qstart, qend);
 	return ans;
}
 

void updateOne(int root, int nstart, int nend, int index, int addVal)
{
    if(nstart == nend)
    {
        segTree[root].val += addVal;
        return;
    }
    int mid = (nstart + nend) / 2;
    if(index <= mid)//       
        updateOne(root*2, nstart, mid, index, addVal);
    else 
		updateOne(root*2+1, mid+1, nend, index, addVal);
    segTree[root].val = segTree[root*2].val + segTree[root*2+1].val;
}

 
3. 나의 수확
① 우리 가 배열 로 선분 트 리 를 저장 할 때 유효한 공간 은 2n - 1 이지 만 실제 공간 은 이렇게 많 지 않 습 니 다. 실제 공간 은 이 진 트 리 의 노드 수 입 니 다. 예 를 들 어 제목 에서 N < = 50000 을 요 구 했 습 니 다. 처음에 제 가 설정 한 maxn 은 500005 이 었 습 니 다. OJ 는 Runtime Error (ACCESS VIOLATION), 즉 배열 이 경 계 를 넘 었 습 니 다. maxn 을 150005 로 설정 할 때 AC 에 성공 하 였 습 니 다.
② 이러한 입력 기법 에 대해 서 는 코드 를 보 세 요!
 
4. 문제 코드
#include 
#include 
#include 
using namespace std;
const int maxn = 150005;

struct SegTreeNode
{
    int val;
}segTree[maxn]; 		//     

void build(int root, int arr[], int istart, int iend)
{
    if(istart == iend)					//    
        segTree[root].val = arr[istart];
    else{
        int mid = (istart + iend) / 2;
        build(root*2, arr, istart, mid);//       
        build(root*2+1, arr, mid+1, iend);//       
   		segTree[root].val = segTree[root*2].val + segTree[root*2+1].val; 
    }
}
 
int query(int root, int nstart, int nend, int qstart, int qend)
{
    //                
    if(qstart <= nstart && qend >= nend)
        return segTree[root].val;
    int mid = (nstart + nend) / 2;
 	int ans = 0;
 	if(qstart<=mid)	ans += query(root*2, nstart, mid, qstart, qend);
 	if(qend>mid)	ans += query(root*2+1, mid + 1, nend, qstart, qend);
 	return ans;
}
 

void updateOne(int root, int nstart, int nend, int index, int addVal)
{
    if(nstart == nend)
    {
        segTree[root].val += addVal;
        return;
    }
    int mid = (nstart + nend) / 2;
    if(index <= mid)//       
        updateOne(root*2, nstart, mid, index, addVal);
    else 
		updateOne(root*2+1, mid+1, nend, index, addVal);
    segTree[root].val = segTree[root*2].val + segTree[root*2+1].val;
}

int main()
{
	int T,n,arr[maxn],a,b,kase=0;
	scanf("%d",&T);
	while(T--){
		kase++;
		printf("Case %d:
",kase); scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&arr[i]); } build(1,arr,1,n); char ch[10]; while(scanf("%s",ch)&&ch[0]!='E'){ scanf("%d %d",&a,&b); if(ch[0]=='Q'){ printf("%d
",query(1,1,n,a,b)); } else if(ch[0]=='A'){ updateOne(1,1,n,a,b); } else{ updateOne(1,1,n,a,-b); } } } return 0; }

 
 
다음으로 전송:https://www.cnblogs.com/xzxl/p/7270402.html

좋은 웹페이지 즐겨찾기