# 【线段树】【P4062】 [Code+#1]Yazid 的新生舞会

## Solution

$\sum_{i = l}^{r} \sum_{j = -n}^{i - 1} tree_i~=~(r - l + 1) \times \sum_{i = -n}^{l-1} tree_i + \sum_{i = l}^{r} tree_i \times (r - i)~=~(r - l + 1) \times \sum_{i = -n}^{l-1} tree_i + r\sum_{i = l}^{r} tree_i - \sum_{i = l}^{r} tree_i \times i$

## Code

#include <cstdio>
#include <vector>
#include <algorithm>
#ifdef ONLINE_JUDGE
#define freopen(a, b, c)
#endif
#define printf(...)

typedef long long int ll;

namespace IPT {
const int L = 1000000;
char buf[L], *front=buf, *end=buf;
char GetChar() {
if (front == end) {
end = buf + fread(front = buf, 1, L, stdin);
if (front == end) return -1;
}
return *(front++);
}
}

template <typename T>
inline void qr(T &x) {
char ch = IPT::GetChar(), lst = ' ';
while ((ch > '9') || (ch < '0')) lst = ch, ch=IPT::GetChar();
while ((ch >= '0') && (ch <= '9')) x = (x << 1) + (x << 3) + (ch ^ 48), ch = IPT::GetChar();
if (lst == '-') x = -x;
}

namespace OPT {
char buf[120];
}

template <typename T>
inline void qw(T x, const char aft, const bool pt) {
if (x < 0) {x = -x, putchar('-');}
int top=0;
do {OPT::buf[++top] = static_cast<char>(x % 10 + '0');} while (x /= 10);
while (top) putchar(OPT::buf[top--]);
if (pt) putchar(aft);
}

const int maxn = 500005;

int n;
ll ans;
int MU[maxn];
std::vector<int>num[maxn];

struct Tree {
int l, r;
ll sum;
Tree *ls, *rs;
std::pair<ll, ll> v;
std::pair<int, bool> tag;

Tree(const int _l, const int _r) : l(_l), r(_r), sum(((r - l + 1ll) * (r + l)) >> 1), ls(NULL), rs(NULL) {}

inline void maketag(std::pair<int, bool> v) {
if (v.second) {
this->v.first = this->v.second = this->tag.first = 0;
this->tag.second = true;
}
this->v.first += (r - l + 1ll) * v.first;
this->v.second += v.first * sum;
this->tag.first += v.first;
}

inline void pushdown() {
this->ls->maketag(this->tag);
this->rs->maketag(this->tag);
this->tag.first = this->tag.second = 0;
}

inline void pushup() {
this->v.first = this->ls->v.first + this->rs->v.first;
this->v.second = this->ls->v.second + this->rs->v.second;
}

inline bool InRange(const int l, const int r) {
return (this->l >= l) && (this->r <= r);
}

inline bool OutofRange(const int l, const int r) {
return (this->l > r) || (this->r < l);
}
};
Tree *rot;

void build(Tree *const u);
int calc(const int k, const int p);
void update(Tree *const u, const int l, const int r);
std::pair<ll, ll> query(Tree *const u, const int l, const int r);

int main() {
freopen("1.in", "r", stdin);
qr(n); qr(ans); ans = 0;
for (int i = 1; i <= n; ++i) {
qr(MU[i]); num[MU[i]].push_back(i);
}
build(rot = new Tree(-n, n));
for (int k = 0; k < n; ++k) {
rot->maketag(std::make_pair(0, true));
int l = 0, cnt = 0;
for (auto u : num[k]) {
if (u != l) {
int r = u - 1;
int ar = calc(cnt, l), al = calc(cnt, r);
auto ret1 = query(rot, -n, al - 1), ret2 = query(rot, al, ar);
ans += ret1.first * (ar - al + 1) + ret2.first * ar - ret2.second;
update(rot, al, ar);
printf("QWAQ%d %d %lld\n", k, u, ans);
}
int v = calc(++cnt, u);
ans += query(rot, -n, v - 1).first;
printf("QWAQ%d %d %lld\n", k, u, ans);
update(rot, v, v);
l = u + 1;
}
if (l <= n) {
int r = n;
int ar = calc(cnt, l), al = calc(cnt, r);
auto ret1 = query(rot, -n, al - 1), ret2 = query(rot, al, ar);
printf("EMM%lld %lld %lld %lld\n", ret1.first, ret1.second, ret2.first, ret2.second);
ans += ret1.first * (ar - al + 1) + ret2.first * ar - ret2.second;
}
printf("QWQ%d %lld\n", k, ans);
}
qw(ans, '\n', true);
return 0;
}

void update(Tree *const u, const int l, const int r) {
if (u->InRange(l, r)) {
u->maketag(std::make_pair(1, false));
} else if (!u->OutofRange(l, r)) {
u->pushdown();
update(u->ls, l, r); update(u->rs, l, r);
u->pushup();
}
printf("UPD%d %d %d %d %d %d\n", u->l, u->r, l, r, u->v.first, u->v.second);
}

std::pair<ll, ll> query(Tree *const u, const int l, const int r) {
printf("EMMQAQ%d %d %d %d %d\n", u->l, u->r, l, r, u->v.first);
if (u->InRange(l, r)) {
return u->v;
} else if (u->OutofRange(l, r)) {
return std::make_pair(0ll, 0ll);
} else {
u->pushdown();
auto rl = query(u->ls, l, r), rr = query(u->rs, l, r);
return std::make_pair(rl.first + rr.first, rl.second + rr.second);
u->pushup();
}
}

inline int calc(const int k, const int p) {
return (k << 1) - p;
}

void build(Tree *const u) {
if (u->l == u->r) return;
int mid = (u->l + u->r) >> 1;
build(u->ls = new Tree(u->l, mid)); build(u->rs = new Tree(mid + 1, u->r));
}


## Summary

posted @ 2019-07-09 20:51  一扶苏一  阅读(203)  评论(0编辑  收藏  举报