따뜻 한 출석 문제, 노 스 웨 스 턴 대 합숙 대 선발 전 (재현전), 선분 수 구간 수정

4821 단어 데이터 구조
링크:https://ac.nowcoder.com/acm/contest/892/D 우 객 망
제목: 따뜻 한 출석 체크
n 길이 의 서열 을 드 리 겠 습 니 다. 처음에는 1, 2, 3... n 으로 m 번 조작 합 니 다.작업 은 두 가지 가 있 습 니 다. 1 l r 는 구간 [l, r] 을 [1, 2... r - l + 1] 로 2 l r 조회 [l, r] 의 구간 과 입력 설명 을 표시 합 니 다. 첫 번 째 줄 은 2 개의 숫자, n, m (1 < = n, m < = 1e5) 를 포함 합 니 다.
다음은 m 줄 을 포함 합 니 다. 형식 은 문제 면 에서 보 여 준 출력 설명 과 같 습 니 다. 각 조작 2 에 대해 한 줄 의 정 수 를 출력 하여 답 을 표시 합 니 다.
입력
복사 10, 5, 2, 1, 10, 1, 3, 6, 2, 1, 10, 1, 10, 2, 1, 10.
출력
55 47 55
제목 은 따뜻 한 출석 문제 라 고 하 는데 저 는 짙 은 악 의 를 느 꼈 습 니 다. 경기 할 때 선분 나무 로 해 야 한 다 는 것 을 알 았 습 니 다. 그러나 자신의 선분 나 무 는 기본 적 인 것 만 할 수 있 습 니 다. 구간 수정 과 게 으 른 노드 는 자신 이 할 줄 모 릅 니 다. 배 운 선분 나무 모델 은 왼쪽 에서 열 고 오른쪽 에서 닫 으 면 실수 하기 쉽 습 니 다. 이 문 제 를 틈 타 선분 나 무 를 잘 풀 어서 bug 를 오래 조정 하면 복잡 하고 실수 하기 쉽 습 니 다.
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;

const int maxn = 100005;
ll s[4 * maxn], f[4 * maxn];//s        , f        
int n, m, Q; //Q        

void init(int k, int l, int r)  //     
{
	if (l == r)
	{
		s[k] = r;
		return;
	}

	int mid = (l + r) / 2;

		init(k * 2, l, mid);
		init(k * 2 + 1, mid + 1, r);
		s[k] = s[k * 2] + s[k * 2 + 1];//               pushup,         ,       pushdown   。
	
}

ll cal(ll t, int len)//    ,     
{
	return (t + t + len - 1)* len / 2;
}

void pushdown(int k, int l, int r)//      
{
	if (f[k] == 0) return;

	int mid = (l + r) /2;
	f[k * 2] = f[k];
	s[k * 2] = cal(f[k], mid - l + 1);

	f[k * 2 + 1] = f[k] + mid - l + 1;
	s[k * 2 + 1] = cal(f[k * 2 + 1], r - mid);

	f[k] = 0;//        ,    
}


void update(int a, int b, int k, int l, int r)
{
	if (l >= a && r <= b)
	{
		f[k] = Q;//l    Q  k        Q
		s[k] = cal(Q, r - l + 1);
		Q += (r - l + 1);//Q  
		return;
	}
	pushdown(k, l, r);      

	int mid = (l + r) / 2;
	if (a <= mid) update(a, b, k * 2, l, mid);
	if (b > mid) update(a, b, k * 2 + 1, mid + 1, r);
	s[k] = s[k * 2] + s[k * 2 + 1];
}


ll sum(int a, int b, int k, int l, int r)
{
	if (l >= a && r <= b)
		return s[k];

	pushdown(k, l, r);//                     

	ll left = 0, right = 0;
	int mid = (l + r) / 2;;
	if (a <= mid) left = sum(a, b, k * 2, l, mid);
	if (b > mid) right = sum(a, b, k * 2 + 1, mid + 1, r);
	s[k] = s[k * 2] + s[k * 2 + 1];
	return left + right;
}



int main()
{
	ios::sync_with_stdio(false);
	cin >> n >> m;
	init(1, 1, n);

	for (int i = 0; i < m; i++)
	{
		int x, l, r;
		cin >> x >> l >> r;
		if (x == 1)
			Q = 1, update(l, r, 1, 1, n);//    Q   1
		else
			cout << sum(l, r, 1, 1, n) << endl;
	}
}



더 성숙 한 코드 업데이트
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll;
const int maxn = 100005;
ll s[maxn * 4], f[maxn * 4];
int n, m, Q;

void pushup(int k)
{
	s[k] = s[k * 2 + 1] + s[k * 2];
}

void init(int k, int l, int r)
{
	if (l == r) s[k] = r;
	else
	{
		int mid = (l + r) >> 1;
		init(k * 2, l, mid);
		init(k * 2 + 1, mid + 1, r);
		pushup(k);
	}
}

ll cal(ll a, int len)
{
	return (a + a + len - 1)* len / 2;
}

void pushdown(int k, int l, int r)
{
	if (!f[k]) return;

	int mid = (l + r) >> 1;

	f[k * 2] = f[k];
	s[k * 2] = cal(f[k], mid - l + 1);

	f[k * 2 + 1] = f[k] + mid - l + 1;
	s[k * 2 + 1] = cal(f[k * 2 + 1], r - mid);

	f[k] = 0;
}

void update(int a, int b, int k, int l, int r)
{
	if (l >= a && r <= b)
	{
		f[k] = Q;
		s[k] = cal(Q, r - l + 1);
		Q += (r - l + 1);
	}
	else
	{
		pushdown(k, l, r);
		int mid = (l + r) >> 1;
		if (a <= mid) update(a, b, k * 2, l, mid);
		if (b > mid) update(a, b, k * 2 + 1, mid + 1, r);
		pushup(k);
	}
}

ll sum(int a, int b, int k, int l, int r)
{
	if (l >= a && r <= b) return s[k];

	pushdown(k, l, r);
	int mid = (l + r) >> 1;
	ll left = 0, right = 0;
	if (a <= mid) left =  sum(a, b, k * 2, l, mid);
	if (b > mid) right =  sum(a, b, k * 2 + 1, mid + 1, r);
	return left + right;
}

int main()
{
	ios::sync_with_stdio(false);
	cin >> n >> m;
	init(1, 1, n);
	for (int i = 0; i < m; i++)
	{
		int x, l, r;
		cin >> x >> l >> r;
		if (x == 1)
		{
			Q = 1;
			update(l, r, 1, 1, n);
		}
		else
			cout << sum(l, r, 1, 1, n) << endl;
	}
}

좋은 웹페이지 즐겨찾기