1、HDU 1166 敌兵布阵
单点更新
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
struct SegTree {
int left, right;
LL sum;
};
const int maxn = 50000 + 5;
int num[maxn];
SegTree Tree[maxn * 4];
char cmd[10];
void Build(int low, int high, int index);
void Update(int target, int add, int index);
LL Query(int low, int high, int index);
int main()
{
// freopen("in.txt", "r", stdin);
int T;
scanf("%d", &T);
int Case = 0;
while (T--) {
++Case;
printf("Case %d:\n", Case);
int N;
scanf("%d", &N);
for (int i=1; i<=N; ++i) {
scanf("%d", &num[i]);
}
Build(1, N, 1);
while (scanf("%s", cmd) && strcmp(cmd, "End") != 0) {
int i, j;
scanf("%d%d", &i, &j);
if (strcmp(cmd, "Add") == 0) {
Update(i, j, 1);
} else if (strcmp(cmd, "Sub") == 0) {
Update(i, -j, 1);
} else if (strcmp(cmd, "Query") == 0) {
printf("%I64d\n", Query(i, j, 1));
}
}
}
return 0;
}
void Build(int low, int high, int index)
{
Tree[index].left = low;
Tree[index].right = high;
if (low == high) {
Tree[index].sum = num[low];
return;
} else {
int mid = low + (high-low)/2;
Build(low, mid, index*2);
Build(mid+1, high, index*2+1);
Tree[index].sum = Tree[index*2].sum + Tree[index*2+1].sum;
}
}
void Update(int target, int add, int index)
{
if (Tree[index].left == Tree[index].right && Tree[index].left == target) {
Tree[index].sum += add;
return;
} else {
int mid = Tree[index].left + (Tree[index].right - Tree[index].left)/2;
if (target <= mid) {
Update(target, add, index*2);
} else {
Update(target, add, index*2+1);
}
Tree[index].sum = Tree[index*2].sum + Tree[index*2+1].sum;
}
}
LL Query(int low, int high, int index)
{
if (Tree[index].left == low && Tree[index].right == high) {
return Tree[index].sum;
} else {
int mid = Tree[index].left + (Tree[index].right - Tree[index].left)/2;
if (high <= mid) {
return Query(low, high, index*2);
} else if (low > mid) {
return Query(low, high, index*2+1);
} else {
return Query(low, mid, index*2) + Query(mid+1,high, index*2+1);
}
}
}
2、HDU 1754 I Hate It
单点更新
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct SegTree {
int left, right;
int Max;
};
const int maxn = 200000 + 5;
int Grade[maxn];
SegTree Tree[maxn * 4];
char cmd[2];
void Build(int low, int high, int index);
void Update(int target, int num, int index);
int Query(int low, int high, int index);
int main()
{
// freopen("in.txt", "r", stdin);
int N, M;
while (scanf("%d%d", &N, &M) != EOF) {
for (int i=1; i<=N; ++i) {
scanf("%d", &Grade[i]);
}
Build(1, N, 1);
int A, B;
for (int i=0; i<M; ++i) {
scanf("%s%d%d", cmd, &A, &B);
if (cmd[0] == 'U') {
Update(A, B, 1);
} else {
printf("%d\n", Query(A, B, 1));
}
}
}
return 0;
}
void Build(int low, int high, int index)
{
Tree[index].left = low;
Tree[index].right = high;
if (low == high) {
Tree[index].Max = Grade[Tree[index].left];
return;
} else {
int mid = low + (high-low)/2;
Build(low, mid, index*2);
Build(mid+1, high, index*2+1);
Tree[index].Max = max(Tree[index*2].Max, Tree[index*2+1].Max);
}
}
void Update(int target, int num, int index)
{
if (Tree[index].left == Tree[index].right && Tree[index].left == target) {
Tree[index].Max = num;
return;
} else {
int mid = Tree[index].left + (Tree[index].right - Tree[index].left)/2;
if (target <= mid) {
Update(target, num, index*2);
} else {
Update(target, num, index*2+1);
}
Tree[index].Max = max(Tree[index*2].Max, Tree[index*2+1].Max);
}
}
int Query(int low, int high, int index)
{
if (Tree[index].left == low && Tree[index].right == high) {
return Tree[index].Max;
} else {
int mid = Tree[index].left + (Tree[index].right - Tree[index].left)/2;
if (high <= mid) {
return Query(low, high, index*2);
} else if (low > mid) {
return Query(low, high, index*2+1);
} else {
return max(Query(low, mid, index*2), Query(mid+1,high, index*2+1));
}
}
}
3、HDU 1698 Just a Hook
区间更新
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct SegTree {
int left, right;
int color;
};
const int maxn = 100000 + 5;
SegTree Tree[maxn * 4];
void Build(int low, int high, int index);
void Update(int low, int high, int color, int index);
int Query(int low, int high, int index);
int main()
{
// freopen("in.txt", "r", stdin);
int T;
int N, Q;
while (scanf("%d", &T) != EOF) {
int Case = 0;
while (T--) {
scanf("%d%d", &N, &Q);
Build(1, N, 1);
int X, Y, Z;
for (int i=0; i<Q; ++i) {
scanf("%d%d%d", &X, &Y, &Z);
Update(X, Y, Z, 1);
}
++Case;
printf("Case %d: The total value of the hook is %d.\n", Case, Query(1, N, 1));
}
}
return 0;
}
void Build(int low, int high, int index)
{
Tree[index].left = low;
Tree[index].right = high;
Tree[index].color = 1;
if (low == high) {
return;
} else {
int mid = low + (high-low)/2;
Build(low, mid, index*2);
Build(mid+1, high, index*2+1);
}
}
void Update(int low, int high, int color, int index)
{
if (Tree[index].color == color || (Tree[index].left == low && Tree[index].right == high)) {
Tree[index].color = color;
return;
} else {
if (Tree[index].color != 0) {
Tree[index*2].color = Tree[index].color;
Tree[index*2+1].color = Tree[index].color;
Tree[index].color = 0;
}
int mid = Tree[index].left + (Tree[index].right - Tree[index].left)/2;
if (high <= mid) {
Update(low, high, color, index*2);
} else if (low > mid) {
Update(low, high, color, index*2+1);
} else {
Update(low, mid, color, index*2);
Update(mid+1, high, color, index*2+1);
}
}
}
int Query(int low, int high, int index)
{
int mid = Tree[index].left + (Tree[index].right - Tree[index].left)/2;
if (Tree[index].left == low && Tree[index].right == high) {
if (Tree[index].color != 0) {
return Tree[index].color * (high-low+1);
} else {
return Query(low, mid, index*2) + Query(mid+1, high, index*2+1);
}
} else {
if (high <= mid) {
return Query(low, high, index*2);
} else if (low > mid) {
return Query(low, high, index*2+1);
} else {
return Query(low, mid, index*2) + Query(mid+1, high, index*2+1);
}
}
}
4、POJ 3468 A Simple Problem with Integers
区间更新
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long LL;
struct SegTree {
int left, right;
LL sum;
LL val;
};
const int maxn = 100000 + 5;
int num[maxn];
SegTree Tree[maxn * 4];
char cmd[2];
void Build(int low, int high, int index);
void Update(int low, int high, int add, int index);
LL Query(int low, int high, int index);
int main()
{
// freopen("in.txt", "r", stdin);
int N, Q;
scanf("%d%d", &N, &Q);
for (int i=1; i<=N; ++i) {
scanf("%d", &num[i]);
}
Build(1, N, 1);
int a, b, c;
for (int i=0; i<Q; ++i) {
scanf("%s", cmd);
if (cmd[0] == 'Q') {
scanf("%d%d", &a, &b);
printf("%I64d\n", Query(a, b, 1));
} else {
scanf("%d%d%d", &a, &b, &c);
Update(a, b, c, 1);
}
}
return 0;
}
void Build(int low, int high, int index)
{
Tree[index].left = low;
Tree[index].right = high;
Tree[index].val = 0;
if (low == high) {
Tree[index].sum = num[low];
return;
} else {
int mid = low + (high-low)/2;
Build(low, mid, index*2);
Build(mid+1, high, index*2+1);
Tree[index].sum = Tree[index*2].sum + Tree[index*2+1].sum;
}
}
void Update(int low, int high, int add, int index)
{
if (Tree[index].left == low && Tree[index].right == high) {
Tree[index].val += add;
return;
} else {
Tree[index].sum += add * (high-low+1);
int mid = Tree[index].left + (Tree[index].right - Tree[index].left)/2;
if (high <= mid) {
Update(low, high, add, index*2);
} else if (low > mid) {
Update(low, high, add, index*2+1);
} else {
Update(low, mid, add, index*2);
Update(mid+1, high, add, index*2+1);
}
}
}
LL Query(int low, int high, int index)
{
if (Tree[index].left == low && Tree[index].right == high) {
return Tree[index].sum + (high-low+1) * Tree[index].val;
} else {
Tree[index].sum += (Tree[index].right - Tree[index].left+1) * Tree[index].val;
int mid = Tree[index].left + (Tree[index].right - Tree[index].left)/2;
Update(Tree[index].left, mid, Tree[index].val, index*2);
Update(mid+1, Tree[index].right, Tree[index].val, index*2+1);
Tree[index].val = 0;
if (high <= mid) {
return Query(low, high, index*2);
} else if (low > mid) {
return Query(low, high, index*2+1);
} else {
return Query(low, mid, index*2) + Query(mid+1, high, index*2+1);
}
}
}
5、HDU 1394 Minimum Inversion Number
题意:
给一个长度为n的序列,序列中的数num[i]的取值范围为[0,n-1],且各不相等
每次把序列的第一个数移动到最后,得到一个新的序列
求最小逆序数
逆序数的概念:
对于n个不同的元素,先规定各元素之间有一个标准次序(例如n个 不同的自然数,可规定从小到大为标准次序),于是在这n个元素的任一排列中,当某两个元素的先后次序与标准次序不同时,就说有1个逆序。一个排列中所有逆序总数叫做这个排列的逆序数
解题思路:
线段树单点更新
先求出给定序列的逆序数
如果序列的第一个数为x
每次移动后
比x小的数的逆序数都减一,总共-x
比x大的数的逆序数都加一,总共+n-x-1
所以每次移动后的逆序数为 sum -x + n-x-1
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
struct SegTree {
int left, right;
int sum;
};
const int maxn = 5000 + 5;
int num[maxn];
SegTree Tree[maxn * 4];
void Build(int low, int high, int index);
void Update(int target, int index);
int Query(int low, int high, int index);
int main()
{
// freopen("in.txt", "r", stdin);
int n;
while (scanf("%d", &n) != EOF) {
Build(0, n-1, 1);
int sum = 0;
for (int i=0; i<n; ++i) {
scanf("%d", &num[i]);
sum += Query(num[i], n-1, 1);
Update(num[i], 1);
}
int ans = sum;
for (int i=0; i<n; ++i) {
sum = sum - num[i] + (n-num[i]-1);
if (sum < ans) {
ans = sum;
}
}
printf("%d\n", ans);
}
return 0;
}
void Build(int low, int high, int index)
{
Tree[index].left = low;
Tree[index].right = high;
Tree[index].sum = 0;
if (low == high) {
return;
} else {
int mid = low + (high-low)/2;
Build(low, mid, index*2);
Build(mid+1, high, index*2+1);
}
}
void Update(int target, int index)
{
if (Tree[index].left == Tree[index].right) {
Tree[index].sum = 1;
return;
} else {
int mid = Tree[index].left + (Tree[index].right - Tree[index].left)/2;
if (target <= mid) {
Update(target, index*2);
} else {
Update(target, index*2+1);
}
Tree[index].sum = (Tree[index*2].sum + Tree[index*2+1].sum);
}
}
int Query(int low, int high, int index)
{
if (Tree[index].left == low && Tree[index].right == high) {
return Tree[index].sum;
} else {
int mid = Tree[index].left + (Tree[index].right - Tree[index].left)/2;
if (high <= mid) {
return Query(low, high, index*2);
} else if (low > mid) {
return Query(low, high, index*2+1);
} else {
return (Query(low, mid, index*2) + Query(mid+1,high, index*2+1));
}
}
}