好象這是liu_runda出的HEOI模擬賽來的. 感覺作爲模擬WC還是簡單了些.
Description
給一個底面爲\(n \times n\)的, 單位立方體堆疊成的幾何體的主視圖和側視圖.
在沒有俯視圖的情況下, 計算最多可以有多少個立方體.
\(n \le x10^5\).
Solution
思路還是很自然的, 就一路從暴力到正解.
先想暴力, 發現一個\((i,j)\)的位置就是\(\min{(a_i, b_j)}\). 就可以\(n^2\)了.
然後發現不修改的話可以排序後二分.
然後發現修改一邊也可以排序後二分.
然後發現都修改可以平衡樹上二分.
做完啦.
/*
@Date : 2019-01-16 08:30:00
@Author : Curtis Nishikino ([email protected])
@Link : https://nishikinocurtis.github.io
*/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cctype>
#include <vector>
#include <queue>
#include <stack>
#include <cmath>
#include <set>
#include <map>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
typedef pair<int, int> pii;
inline int rd() {
register int x = 0, f = 0, c = getchar();
while (!isdigit(c)) {
if (c == '-') f = 1;
c = getchar();
}
while (isdigit(c)) x = x * 10 + (c ^ 48), c = getchar();
return f ? -x : x;
}
const int maxn = 2e+5 + 5;
int n, m, a[maxn], b[maxn];
ll ans;
struct Treap {
struct node {
int ch[2], v, siz, k, w;
ll sum;
node() {
ch[1] = ch[0] = 0;
v = w = siz = k = 0;
}
}t[maxn];
int ptr, rt;
#define lson t[p].ch[0]
#define rson t[p].ch[1]
inline int newnode(int val) {
++ptr;
t[ptr].v = val; t[ptr].w = rand();
t[ptr].siz = t[ptr].k = 1;
t[ptr].sum = val;
return ptr;
}
inline void pushup(int p) {
t[p].siz = t[lson].siz + t[rson].siz + t[p].k;
t[p].sum = t[lson].sum + t[rson].sum + 1ll * t[p].v * t[p].k;
}
inline void rturn(int &p) {
int q = lson;
lson = t[q].ch[1]; t[q].ch[1] = p; p = q;
pushup(rson);
pushup(p);
}
inline void lturn(int &p) {
int q = rson;
rson = t[q].ch[0]; t[q].ch[0] = p; p = q;
pushup(lson);
pushup(p);
}
void Insert(int &p, int x) {
//printf("%d\n", p);
if (!p) {
p = newnode(x);
return;
}
t[p].siz++; t[p].sum += x;
if (t[p].v == x) {
t[p].k++;
//t[p].sum += x;
return;
} else if (t[p].v < x) {
Insert(rson, x);
if (t[rson].w < t[p].w) lturn(p);
} else {
Insert(lson, x);
if (t[lson].w < t[p].w) rturn(p);
}
}
void Delete(int &p, int x) {
if (!p) return;
if (t[p].v == x) {
if (t[p].k > 1) t[p].k--, t[p].siz--, t[p].sum -= x;
else {
if (!(lson && rson)) p = lson + rson;
else if (t[rson].w > t[lson].w)
rturn(p), Delete(p, x);
else lturn(p), Delete(p, x);
}
} else {
t[p].siz--; t[p].sum -= x;
if (t[p].v < x) Delete(rson, x);
else Delete(lson, x);
}
}
ll GetLower(int p, int k) {
//printf("%d %d %d %lld\n", p, t[p].v, k, t[p].sum);
if (!p) return 0;
if (t[p].v == k) {
//printf("ret %lld\n", t[p].sum - t[rson].sum);
return t[p].sum - t[rson].sum;
} else if (t[p].v < k) {
ll ret = t[p].sum - t[rson].sum + GetLower(rson, k);
//printf("ret %lld\n", ret);
return ret;
} else {
ll ret = GetLower(lson, k);
//printf("ret %lld\n", ret);
return ret;
}
}
int GetLowerSize(int p, int k) {
if (!p) return 0;
if (t[p].v == k) {
return t[p].siz - t[rson].siz;
} else if (t[p].v < k) {
return t[p].siz - t[rson].siz + GetLowerSize(rson, k);
} else {
return GetLowerSize(lson, k);
}
}
#undef lson
#undef rson
}A, B;
int main() {
freopen("graph.in", "r", stdin);
freopen("graph.out", "w", stdout);
n = rd();
for (int i = 1; i <= n; ++i) {
a[i] = rd(); A.Insert(A.rt, a[i]);
//printf("%d\n", A.rt);
//printf("%d\n", A.t[A.rt].siz);
}
for (int i = 1; i <= n; ++i) {
b[i] = rd(); B.Insert(B.rt, b[i]);
//printf("%d\n", B.rt);
}
for (int i = 1; i <= n; ++i) {
ll lsum = B.GetLower(B.rt, a[i]);
int rsiz = n - B.GetLowerSize(B.rt, a[i]);
//printf("%lld %d\n", lsum, rsiz);
//puts("---");
ans += lsum + 1ll * rsiz * a[i];
}
printf("%lld\n", ans);
m = rd();
int typ, p, x;
while (m--) {
typ = rd(); p = rd(); x = rd();
if (typ) {
ll lsum = A.GetLower(A.rt, b[p]);
int rsiz = n - A.GetLowerSize(A.rt, b[p]);
ans -= lsum + 1ll * rsiz * b[p];
B.Delete(B.rt, b[p]);
b[p] = x;
lsum = A.GetLower(A.rt, b[p]);
rsiz = n - A.GetLowerSize(A.rt, b[p]);
ans += lsum + 1ll * rsiz * b[p];
B.Insert(B.rt, b[p]);
} else {
ll lsum = B.GetLower(B.rt, a[p]);
int rsiz = n - B.GetLowerSize(B.rt, a[p]);
ans -= lsum + 1ll * rsiz * a[p];
A.Delete(A.rt, a[p]);
a[p] = x;
lsum = B.GetLower(B.rt, a[p]);
rsiz = n - B.GetLowerSize(B.rt, a[p]);
ans += lsum + 1ll * rsiz * a[p];
A.Insert(A.rt, a[p]);
}
printf("%lld\n", ans);
}
fclose(stdin);
fclose(stdout);
return 0;
}