本来使用 ppt 汇报的,这里转成图片了~
主要介绍原理和讲解 POJ1990~
that is a test
this is a test
完整代码:
#define _CRT_SECURE_NO_WARNINGS | |
#include <iostream> | |
#include <cstdio> | |
#include <algorithm> | |
using namespace std; | |
struct node | |
{ | |
int index; //x 坐标 | |
int vol; // 音量 | |
} cow[20002]; | |
long long C1[20002]; // 位置在 i 左侧的牛的数量 | |
long long C2[20002]; // 位置在 i 左侧的牛的坐标的和 | |
long long N; // 牛的数量 | |
// 按音量从小到大排序 | |
bool compare(node a, node b) | |
{ | |
return a.vol < b.vol; | |
} | |
// 获取最低位 1 | |
long long getlowest_1_bit(long long x) | |
{ | |
return x & (-x); // 原码和反码加 1 (即负数) 的 & amp; 就是最低位的 1 | |
} | |
// 用 value 更新结点 x 的值 | |
void update(int x, int value, long long C[]) | |
{ | |
for (int i = x; i <= 20000; i += getlowest_1_bit(i)) // 每次更新 i 直到越界 | |
{ | |
C[i] += value; // 只需按照顺序向上更新 | |
} | |
} | |
// 查询高于结点 x 的值之和 | |
long long inquiry(int x, long long C[]) | |
{ | |
long long sum = 0; | |
for (int i = x; i > 0; i -= getlowest_1_bit(i)) // 每次更新 i 直到越界 | |
{ | |
sum += C[i]; // 路径上的值相加 | |
} | |
return sum; | |
} | |
int main() | |
{ | |
scanf("%d", &N); | |
long long sum_leftindex; //i 左侧的坐标和 | |
long long sum_leftcow; //i 左侧的牛数量 | |
long long ans = 0; // 记录答案 | |
long long sum = 0; // 记录总的坐标和 | |
for (int i = 1; i <= N; i++) // 读入 N 头牛的数据 | |
{ | |
scanf("%d %d", &cow[i].vol, &cow[i].index); | |
} | |
sort(cow + 1, cow + 1 + N, compare); // 音量排序 | |
for (int i = 1; i <= N; i++) | |
{ | |
sum_leftcow = inquiry(cow[i].index, C1); | |
sum_leftindex = inquiry(cow[i].index, C2); | |
//i 左边的牛的音量等于牛 i 的坐标 * 牛 i 左侧牛的数量 - 牛 i 左侧牛的坐标和 | |
ans += cow[i].vol * (sum_leftcow * cow[i].index - sum_leftindex); | |
//i 右边的牛的音量等于牛 i 右侧牛的坐标和 - 牛 i 的坐标 * 牛 i 右侧牛的数量 | |
ans += cow[i].vol * (sum - sum_leftindex - cow[i].index * (i - sum_leftcow - 1)); | |
update(cow[i].index, 1, C1); // C1 加入这头牛 | |
update(cow[i].index, cow[i].index, C2); // C2 加入该牛的坐标 | |
sum += cow[i].index; | |
} | |
printf("%lld", ans); | |
return 0; | |
} |