线段树(ALGO-8重刷)
#include <iostream>#define max(a,b) a > b ? a : b;using namespace std;const int MAXN = 1e2 + 1;int num = 0;/*线段树元素结构体*/struct NODE {int l;int r;int maxValue;int sum;}node[MAXN];/*初始化线段树*/void init(int i,int l,int r) {node[i].l = l;node[i].r = r;node[i].maxValue = 0;node[i].sum = 0;num++;if (node[i].l != node[i].r) {int mid = (l + r) / 2;init(2 * i,l, mid);init(2 * i + 1,mid + 1, r);}}/*插入线段树元素*/void insert(int i,int pos,int value) {if (node[i].l == node[i].r) { //错误五:“node[i].l = node[i].r” 判断条件错误,排查费时node[i].maxValue = value;node[i].sum = value;return; //错误一:遗漏return}int mid = (node[i].l + node[i].r) / 2;if (pos <= mid) insert(2 * i, pos, value);else insert(2 * i + 1, pos, value);/*同时初始化最大权值和总权值*/node[i].maxValue = max(node[2 * i].maxValue, node[2 * i + 1].maxValue);node[i].sum = node[2 * i].sum + node[2 * i + 1].sum;}/*查找范围内元素个体最大权值*/int search_max(int i, int x, int y) {if (node[i].l == x && node[i].r == y) { //错误三:node[i].l == node[i].r 条件判断错误return node[i].maxValue;}int mid = (node[i].l + node[i].r) / 2;if (y <= mid) return search_max(2 * i, x, y); //错误二:还是遗漏returnelse if (x > mid) return search_max(2 * i + 1, x, y);else {return max(search_max(2 * i, x, mid), search_max(2 * i + 1, mid + 1, y));}}/*查找范围内元素的权值和*/int search_sum(int i, int x, int y) {if (x == node[i].l && y == node[i].r) { //错误四:还是 node[i].l == node[i].r 条件判断错误return node[i].sum;}int mid = (node[i].l + node[i].r) / 2;if (y <= mid) return search_sum(2 * i, x, y);else if (x > mid) return search_sum(2 * i + 1, x, y);else {return search_sum(2 * i, x, mid) + search_sum(2 * i + 1, mid + 1, y);}}int main() {int n, m;cin >> n >> m;/*初始化*/init(1,1,n);/*看树*/cout << "show tree after init" << endl;int count = 1;for (int i = 1; i <= num; i++) {if (i >= pow(2, count)) {cout << endl;count++;}cout << "( " << node[i].l << ',' << node[i].r << " )";}cout << endl;/*插入*/int value;for (int i = 1; i <= n; i++) {cin >> value;insert(1, i, value);}/*再看树*/cout << "show tree after insert" << endl;count = 1;for (int i = 1; i <= num; i++) {if (i >= pow(2, count)) {cout << endl;count++;}cout << "( max:" << search_max(i,node[i].l,node[i].r) <<" ; sum:"<< search_sum(i, node[i].l, node[i].r) << " )";}cout << endl;/*题目要求*/for (int i = 1; i <= m; i++) {int p, x, y;cin >> p >> x >> y;if (p == 1) insert(1, x, y);if (p == 2) cout << "sum = "<< search_sum(1, x, y) << endl;if (p == 3) cout << "max = "<< search_max(1, x, y) << endl;}return 0;}/*4 31 2 3 42 1 31 4 33 1 4*/
线段树提升,懒惰标记
#include <iostream>#include <cmath>using namespace std;const int MAXN = 1e2 + 1;int num = 0;struct NODE {int l;int r;int sum;int tag; //懒惰标记}node[MAXN];void init(int i, int left, int right); //初始化线段树void chahgeRespectively(int i, int pos, int value); //单点更新(错误1)void changeSegment(int i, int x, int y, int value); //区间更新(错误5)int findSum(int i, int x, int y); //查询区间内权值总和(错误2,4,6)void pushDown(int i); //下推标记(错误3)void update(int i); //节点递归更新void showTree(); //看树int main() {int n, x, y, t, pos;cin >> x >> y;init(1, x, y);showTree(); //showTree/*单点更新*/cin >> n;for (int i = 0; i < n; i++) {cin >> pos >> t;chahgeRespectively(1, pos, t);}showTree(); //showTree/*区间更新测试*/changeSegment(1, 1, 3, 1);showTree(); //showTreechangeSegment(1, 2, 4, 2);showTree(); //showTree/*查询函数测试*/cout << "test F_findSum:" << endl;showTree();cout<<findSum(1, 2, 4);return 0;}/*初始化结点*/void init(int i, int left, int right) {node[i].l = left;node[i].r = right;node[i].sum = 0;node[i].tag = 0;num++;if (node[i].l != node[i].r) {int mid = (node[i].l + node[i].r) / 2;init(2 * i, left, mid);init(2 * i + 1, mid + 1, right);}}/*节点递归更新*/void update(int i) {node[i].sum = node[2 * i].sum + node[2 * i + 1].sum;return;}/*下推一次懒惰标记*/void pushDown(int i) {cout << endl << "i = " << i << endl;if (node[i].l == node[i].r) //错误三:“叶节点无需操作”,部分情况下节点tag要清零{node[i].tag = 0; //即使这次叶节点tag不清零答案没影响sumshowTree();return;}/*更新到左右子节点,清除自身tag*/node[2 * i].sum += (node[2 * i].r - node[2 * i].l + 1) * node[i].tag;node[2 * i + 1].sum += (node[2 * i + 1].r - node[2 * i + 1].l + 1) * node[i].tag;node[2 * i].tag += node[i].tag;node[2 * i + 1].tag += node[i].tag;node[i].tag = 0;showTree();return;}/*单点更新*/void chahgeRespectively(int i,int pos,int value) {if (node[i].l == node[i].r) {node[i].sum = value;return; //错误一:再次漏了return}int mid = (node[i].l + node[i].r) / 2;if (pos <= mid) { chahgeRespectively(2 * i, pos, value); }if (pos > mid) { chahgeRespectively(2 * i + 1, pos, value); }update(i);}/*区间更新*/void changeSegment(int i, int x, int y, int value) {if (node[i].tag) pushDown(i); //如果已经有标记,下推标记if (node[i].l == x && node[i].r == y) { //正中靶心,信息只更新到该节点,并打上标记node[i].sum += (node[i].r - node[i].l + 1) * value;node[i].tag += value;return;}int mid = (node[i].l + node[i].r) / 2;if (y <= mid) {changeSegment(2 * i, x, y, value);}else if (x > mid) { //错误五:同错误四,else if (x >= mid)找区间判断条件错误changeSegment(2 * i + 1, x, y, value);}else {changeSegment(2 * i, x, mid, value);changeSegment(2 * i + 1, mid + 1, y, value);}update(i);}/*查询区间内权值总和*/int findSum(int i, int x, int y) {if (node[i].tag) pushDown(i); //查询节点有标记,下推标记if (node[i].l == x && node[i].r == y) { //正中靶心return node[i].sum;}int mid = (node[i].l + node[i].r) / 2;if (y <= mid) return findSum(2 * i, x, y); //错误二:if (y <= node[i].l) 条件写错else if(x > mid) return findSum(2 * i + 1, x, y); //错误四:else if(x >= mid) 条件写错else return findSum(2 * i, x, mid) + findSum(2 * i + 1, mid + 1, y); //错误六:引用范围错误,压根没用到mid}/*查看线段树*/void showTree() {cout << "show tree below" << endl;int count = 1;for (int i = 1; i <= num; i++) {if (i >= pow(2, count)) {cout << endl;count++;}cout << "( " << node[i].l << ',' << node[i].r <<",sum:"<<node[i].sum<<",tag:"<<node[i].tag<< " )";}cout <<endl<<"Dode"<<endl;}/*1 551 12 23 34 45 5*/
repeat 1
重复犯了上次的两个错误,并犯了两个新错误
void changeSegment(int i, int x, int y, int value) {if (node[i].tag) pushDown(i); //有tag,下推一次if (x == node[i].l && node[i].r == y) {node[i].sum += (node[i].r - node[i].l + 1) * value;node[i].tag = value;return; //(新)错误三:这次区间更新没有加return}int mid = (node[i].l + node[i].r) / 2;if (y <= mid) changeSegment(2 * i, x, y, value); //错误一:y <= node[i].l 这种重复性错误else if (x > mid) changeSegment(2 * i + 1, x, y, value); //能不能长点脑子.jpgelse {changeSegment(2 * i, x, mid, value);changeSegment(2 * i + 1, mid + 1, y, value);}update(i);}void pushDown(int i) {cout << endl << "i = " << i << endl;if (node[i].l == node[i].r) {node[i].tag = 0;showTree();return;}node[2 * i].sum += (node[2 * i].r - node[2 * i].l + 1) * node[i].tag; //(新)错误四:“sum =”错了,是sum +=node[2 * i + 1].sum += (node[2 * i + 1].r - node[2 * i + 1].l + 1) * node[i].tag;node[2 * i].tag += node[i].tag;node[2 * i + 1].tag += node[i].tag;node[i].tag = 0; //错误二,更新左右子节点后,没有清除自身tagshowTree();}
洛谷线段树1
建树插入一气呵成 ```cpp
include
include
using namespace std; const int MAXN = 100010; int n, m; struct NODE { int l; int r; long long tag; long long sum; }node[4*MAXN+2]; int a[MAXN];
void built(int i,int left,int right) {
node[i].l = left;
node[i].r = right;
if (node[i].l == node[i].r) {
node[i].sum = a[left];
return;
}
int mid = (left + right) / 2;
built(2 i, left, mid);
built(2 i + 1, mid + 1, right);
node[i].sum = node[2 i].sum + node[2 i + 1].sum;
}
void pushDown(int i) {
if (node[i].l == node[i].r) {
return;
}
node[2 i].sum += (node[2 i].r - node[2 i].l + 1) node[i].tag;
node[2 i + 1].sum += (node[2 i + 1].r - node[2 i + 1].l + 1) node[i].tag;
node[2 i].tag += node[i].tag;
node[2 i + 1].tag += node[i].tag;
node[i].tag = 0;
}
/chanfeSegment/
void addSegment(int i, int x, int y, int value) {
if (x <= node[i].l && node[i].r <= y) {
node[i].sum += (long long)(node[i].r - node[i].l + 1) value;
node[i].tag += value;
return;
}
if (node[i].tag) pushDown(i);
int mid = (node[i].l + node[i].r) / 2;
if(x <= mid) addSegment(2 i, x, y, value);
if(y > mid) addSegment(2 i + 1, x, y, value);
node[i].sum = node[2 i].sum + node[2 i + 1].sum;
}
/findSum/
long long findSum(int i, int x, int y) {
if (node[i].tag) pushDown(i);
if (node[i].l == x && node[i].r == y) return node[i].sum;
int mid = (node[i].l + node[i].r) / 2;
if (y <= mid) return findSum(2 i, x, y);
else if(x > mid) return findSum(2 i + 1, x, y);
else return findSum(2 i, x, mid) + findSum(2 * i + 1, mid + 1, y);
}
int main() {
cin >> n >> m;
for (int i = 1; i <= n; i++) {
scanf(“%d”, &a[i]);
}
built(1, 1, n);
int p, x, y, k;
for (int i = 1; i <= m; i++) {
//cin >> p;
scanf(“%d”, &p);
if (p == 1) {
//cin >> x >> y >> k;
scanf(“%d%d%d”, &x,&y,&k);
addSegment(1, x, y, k);
}
else if (p == 2) {
//cin >> x >> y;
scanf(“%d%d”, &x,&y);
cout << findSum(1, x, y) << endl;
}
}
}
<a name="qPomY"></a>## 约瑟夫问题- 数学模拟```cpp#include<cstdio>#include <iostream>using namespace std;int i, finds, k, m, begins;int check(int remain){cout << "b = " << begins << ' ' << "m = " << m <<" remain = "<< remain << ' ';int result = (begins + m - 1) % remain;cout << result << ' ' << endl;if (result >= k) {//判断出列的那个人begins = result;return 1;}else { return 0; }}int main() {cin >> k;m = k;while (!finds){cout <<endl<< "m = " << m << endl;finds = 1; begins = 0;//设置第一个for (i = 0; i < k; i++){if (!check(2 * k - i))//如果判断好,就可以退出了……{finds = 0; break;}}m++;}cout<<m-1;//多加了一个,减回去return 0;}
- 数组模拟
- 迭代器模拟
最长公共子序列LCS
- 处理好f[][]和s[]的坐标
```cpp
include
include
using namespace std; const int MAXN = 1e2 + 10; char s1[MAXN]; char s2[MAXN]; int f[MAXN][MAXN]; int m, n;
void LCS(int i, int j) {
if (i == 0 || j == 0) return; //错误1:if (i == 0 && j == 0)
if (s1[i-1] == s2[j-1]) { //错误2:if (s1[i] == s2[j])
LCS(i - 1, j - 1);
cout << s1[i-1]; //错误3:cout << s1[i];
}
else if (f[i][j - 1] > f[i - 1][j]) {
LCS(i, j - 1);
}
else {
LCS(i - 1, j);
}
}
int main() {
gets_s(s1);
gets_s(s2);
m = strlen(s1);
n = strlen(s2);
for (int i = 1; i <= m; i++) {
for (int j = 1; j <= n; j++) {
if (s1[i - 1] == s2[j - 1]) f[i][j] = 1 + f[i - 1][j - 1];
else f[i][j] = max(f[i][j - 1], f[i - 1][j]);
}
}
cout << “LCS长度为:” << f[m][n] << endl;
LCS(m, n);
return 0;
} / algorithms alchemist 5 alhms/ ```
