题目链接:https://ac.nowcoder.com/acm/contest/892/D
时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 65536K,其他语言131072K
64bit IO Format: %lld
题目描述
给你一个长度为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 1 10
2 1 10
输出
55
47
55
解题思路
线段树,对于操作1 l r,就是将[l, r]中的值变成i-l+1,然后按照线段树模板计算就行了。
Accepted Code:
/*
* @Author: lzyws739307453
* @Language: C++
*/
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 100005;
struct edge {
long long val, Mark;
}segTree[MAXN << 2];
void Create(int root, int left, int right) {
segTree[root].Mark = 0;
if (left == right) {
segTree[root].val = left;
return ;
}
int mid = left + ((right - left) >> 1);
Create(root << 1, left, mid);
Create(root << 1 | 1, mid + 1, right);
segTree[root].val = segTree[root << 1].val + segTree[root << 1 | 1].val;
}
void PushDown(int root, int left, int right, long long val) {
int l = right - left + 1;
segTree[root].Mark = val;
segTree[root].val = ((2 * val + l - 1) * l) >> 1;
}
void pushDown(int root, int left, int right) {
if (segTree[root].Mark != 0) {
int mid = left + ((right - left) >> 1);
PushDown(root << 1, left, mid, segTree[root].Mark);
PushDown(root << 1 | 1, mid + 1, right, segTree[root].Mark + mid + 1 - left);
segTree[root].Mark = 0;
}
}
void Update(int root, int Q_left, int Q_right, int left, int right, long long val) {
if (Q_left <= left && Q_right >= right) {
segTree[root].Mark = val;
int l = right - left + 1;
segTree[root].val = ((2 * val + l - 1) * l) >> 1;
return ;
}
pushDown(root, left, right);
int mid = left + ((right - left) >> 1);
if (Q_right <= mid)
Update(root << 1, Q_left, Q_right, left, mid, val);
else if (Q_left > mid)
Update(root << 1 | 1, Q_left, Q_right, mid + 1, right, val);
else {
Update(root << 1, Q_left, mid, left, mid, val);
Update(root << 1 | 1, mid + 1, Q_right, mid + 1, right, val + mid - Q_left + 1);
}
segTree[root].val = segTree[root << 1].val + segTree[root << 1 | 1].val;
}
long long Query_(int root, int Q_left, int Q_right, int left, int right) {
if (Q_left <= left && Q_right >= right)
return segTree[root].val;
pushDown(root, left, right);
int mid = left + ((right - left) >> 1);
if (Q_right <= mid)
return Query_(root << 1, Q_left, Q_right, left, mid);
else if (Q_left > mid)
return Query_(root << 1 | 1, Q_left, Q_right, mid + 1, right);
else return Query_(root << 1, Q_left, mid, left, mid) +
Query_(root << 1 | 1, mid + 1, Q_right, mid + 1, right);
}
int main() {
int n, m, left, right, Judge;
scanf("%d%d", &n, &m);
Create(1, 1, n);
while (m--) {
scanf("%d%d%d", &Judge, &left, &right);
if (Judge - 1)
printf("%lld\n", Query_(1, left, right, 1, n));
else Update(1, left, right, 1, n, 1);
}
return 0;
}