先插个图玩云顶之弈。
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#define ll long long
#define fs first
#define se second
const long double eps = 1e-9;
const int N = 2e5 + 10, M = 2e5 + 10;
const int MOD = 1e9 + 7;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int n , m, _;
std::vector<int> nums;
struct node{
int l, r, cnt;
ll sum;
}tr[N * 21];
/
struct Historical_Segment_Tree{
int idx;
int root[N];
inline int build(int l, int r){
int q = ++ idx;
if(l == r) return q;
int mid = l + r >> 1;
tr[q].l = build(l, mid);//存的是左儿子的编号并非边界
tr[q].r = build(mid + 1, r);
return q;
}
inline int insert(int p, int l, int r, int x, int sum){//需要用到的上一个版本root[i - 1](返回的值是当前版本的root)
int q = ++ idx;
tr[q] = tr[p];//复制上一个节点的信息
if(l == r){
tr[q].cnt += sum;//新版本的信息加1
tr[q].sum += nums[x];
return q;
}
int mid = l + r >> 1;
if(x <= mid) tr[q].l = insert(tr[p].l, l, mid, x, sum);//在左子树则需要更新信息,否则保留原本信息就可以
else tr[q].r = insert(tr[p].r, mid + 1, r, x, sum);
tr[q].cnt = tr[tr[q].l].cnt + tr[tr[q].r].cnt;
tr[q].sum = tr[tr[q].l].sum + tr[tr[q].r].sum;
return q;
}
inline int query(int p, int q, int L, int R, int l, int r){
if(L >= l && R <= r) return tr[q].cnt - tr[p].cnt;
int mid = L + R >> 1;
int cnt = 0;
if(l <= mid) cnt += query(tr[p].l, tr[q].l, L, mid, l, r);
if(r > mid) cnt += query(tr[p].r, tr[q].r, mid + 1, R, l, r);
return cnt;
}
inline ll query(int p, int q, int l, int r, int k){//区间k小
if(l == r) return 1ll * nums[l] * k;
int mid = l + r >> 1;
int cnt = tr[tr[q].l].cnt - tr[tr[p].l].cnt;
if(cnt >= k) return query(tr[p].l, tr[q].l, l, mid, k);
return tr[tr[q].l].sum + query(tr[p].r, tr[q].r, mid + 1, r, k - cnt);
}
}HST;
struct NODE {
int a, b;
bool operator < (const NODE &x) const {
return this->b < x.b;
}
}t[N];
ll ans[N];
auto &root = HST.root;
inline void Solution(int xl, int xr, int yl,int yr) {
if (xl > xr) return ;
int mid = xl + xr >> 1;
int tmp = 0;
ll tans = INF;
for (int i = std::max(mid, yl); i <= yr; i ++) {
ll now = HST.query(root[0], root[i], 0, nums.size() - 1, mid);
now += t[i].b;
if (now < tans) {
tans = now;
tmp = i;
}
}
ans[mid] = tans;
Solution(xl, mid - 1, yl, tmp), Solution(mid + 1, xr, tmp, yr);
}
inline void solve(){
std::cin >> n;
for (int i = 1; i <= n; i ++) {
std::cin >> t[i].a >> t[i].b;
nums.push_back(t[i].a);
}
std::sort(t + 1, t + n + 1);
std::sort(nums.begin(), nums.end());
nums.erase(std::unique(nums.begin(), nums.end()), nums.end());
root[0] = HST.build(0, nums.size() - 1);
for (int i = 1; i <= n; i ++) {
int pos = std::lower_bound(nums.begin(), nums.end(), t[i].a) - nums.begin();
root[i] = HST.insert(root[i - 1], 0, nums.size() - 1, pos, 1);
}
Solution(1, n, 1, n);
for (int i = 1; i <= n; i ++) std::cout << ans[i] << '\n';
}
signed main(void){
_ = 1;
//std::cin >> _;
while(_ --)
solve();
return 0;
}
标签:cnt,return,nums,int,tr,mid,Free,CCPC,2023
From: https://www.cnblogs.com/qdhys/p/17790386.html