https://csustacm.fun/problem/2033

这个题目还是比较简单的,但是比赛的时候没有像清楚,用了一个不太熟悉的数据结构主席树,

所以出现了bug,主席树的bug是真的难找。

这个题目就是首先用dfs+线段树求出每一个富翁的val

然后用二分加线段树来找位置。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <queue>
#include <algorithm>
#include <iostream>
#define inf 0x3f3f3f3f
using namespace std;
const int maxn = 1e5 + ;
typedef long long ll;
ll a[maxn], lazy[maxn * ], sum[maxn * ], flag[maxn * ];
int n, val[maxn];
vector<int>G[maxn];
void add(int u, int v) {
G[u].push_back(v);
G[v].push_back(u);
} void push_down(int id,int l,int r) {
if (lazy[id] == ) return;
// printf("ss id=%d l=%d r=%d\n", id, l, r);
int mid = (l + r) >> ;
if (flag[id << ]) {
// printf("id=%d l=%d r=%d\n", id, l, r);
sum[id << ] += (mid - l + )*lazy[id];
lazy[id << ] += lazy[id];
}
if (flag[id << | ]) {
// printf("ww id=%d l=%d r=%d\n", id, l, r);
sum[id << | ] += (r - mid)*lazy[id];
lazy[id << | ] += lazy[id];
}
lazy[id] = ;
} void update1(int id, int l, int r, int pos,int f) {
if (pos<l || pos>r) return;
if (f == ) flag[id]++;
else if (f == )flag[id]--;
if (l == r) {
sum[id] = ;
return;
}
push_down(id, l, r);
int mid = (l + r) >> ;
if (pos <= mid) update1(id << , l, mid, pos, f);
else update1(id << | , mid + , r, pos, f);
sum[id] = sum[id << ] + sum[id << | ];
} void update2(int id,int l,int r,int x,int y)
{
// printf("id=%d l=%d r=%d x=%d y=%d\n", id, l, r, x, y);
if (x > r || y < l) return;
if (x <= l && y >= r) {
lazy[id] += ;
sum[id] += (r - l + );
return;
}
push_down(id, l, r);
int mid = (l + r) >> ;
if (x <= mid) update2(id << , l, mid, x, y);
if (y > mid) update2(id << | , mid + , r, x, y);
sum[id] = sum[id << ] + sum[id << | ];
} int query(int id,int l,int r,int pos)
{
if (pos<l || pos>r) return ;
if (l == r) return sum[id];
push_down(id, l, r);
int mid = (l + r) >> ;
if (pos <= mid) return query(id << , l, mid, pos);
return query(id << | , mid + , r, pos);
} void dfs(int u, int pre) {
// printf("u=%d a=%lld\n", u, a[u]);
update2(, , n, , a[u]);
update1(, , n, a[u], );
for (int i = ; i < G[u].size(); i++) {
int v = G[u][i];
if (v == pre) continue;
dfs(v, u);
val[a[u]] = min(val[a[u]], query(, , n, a[u]));
// printf("val[%lld]=%d v=%d\n", a[u], val[a[u]], v);
update1(, , n, a[u], );
}
update1(, , n, a[u], );
} int c[maxn]; int lowbit(int x)
{
return x & (-x);
} void update(int x,int k)
{
while (x <= n) {
c[x] += k;
x += lowbit(x);
}
} int getsum(int x)
{
int ans = ;
while (x > ) {
ans += c[x];
x -= lowbit(x);
}
return ans;
} int main() {
int x;
scanf("%d", &n);
memset(val, inf, sizeof(val));
for (int i = ; i <= n; i++) scanf("%d", &x), a[x] = i, G[i].clear();
for (int i = ; i < n; i++) {
int u, v;
scanf("%d%d", &u, &v);
add(u, v);
}
dfs(, -);
for (int i = ; i <= n; i++) if (val[i] >= inf) val[i] = ;
// for (int i = 1; i <= n; i++) printf("val[%d]=%d\n", i, val[i]);
for (int i = ; i <= n; i++) {
int l = , r = n, ans = ;
while (l <= r) {
int mid = (l + r) >> ;
int res = mid - getsum(mid);
if (res >= val[i]) ans = mid, r = mid - ;
else l = mid + ;
}
printf("%d\n", ans);
update(ans, );
}
return ;
}

大富翁 线段树+二分 +dfs的更多相关文章

  1. Codeforces Gym 100803G Flipping Parentheses 线段树+二分

    Flipping Parentheses 题目连接: http://codeforces.com/gym/100803/attachments Description A string consist ...

  2. Codeforces Gym 100231B Intervals 线段树+二分+贪心

    Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...

  3. hdu4614 线段树+二分 插花

    Alice is so popular that she can receive many flowers everyday. She has N vases numbered from 0 to N ...

  4. 洛谷P4344 脑洞治疗仪 [SHOI2015] 线段树+二分答案/分块

    !!!一道巨恶心的数据结构题,做完当场爆炸:) 首先,如果你用位运算的时候不小心<<打成>>了,你就可以像我一样陷入疯狂的死循环改半个小时 然后,如果你改出来之后忘记把陷入死循 ...

  5. CF877E Danil and a Part-time Job 线段树维护dfs序

    \(\color{#0066ff}{题目描述}\) 有一棵 n 个点的树,根结点为 1 号点,每个点的权值都是 1 或 0 共有 m 次操作,操作分为两种 get 询问一个点 x 的子树里有多少个 1 ...

  6. luogu4422 [COCI2017-2018#1] Deda[线段树二分]

    讨论帖:线段树二分的题..我还考场切过..白学 这题我一年前的模拟赛考场还切过,现在就不会了..好菜啊. 显然直接线段树拆成$\log n$个区间,然后每个区间在进行线段树二分即可. UPD:复杂度分 ...

  7. bzoj4399 魔法少女LJJ 线段树合并+线段树二分+并查集

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4399 题解 毒瘤题 \(9\) 种操作还有支持动态图的连通性 仔细读题 $ c<=7$. ...

  8. [BZOJ 2653] middle(可持久化线段树+二分答案)

    [BZOJ 2653] middle(可持久化线段树+二分答案) 题面 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序 ...

  9. Educational Codeforces Round 64 (Rated for Div. 2) (线段树二分)

    题目:http://codeforces.com/contest/1156/problem/E 题意:给你1-n  n个数,然后求有多少个区间[l,r] 满足    a[l]+a[r]=max([l, ...

随机推荐

  1. 在类的外面调用类的private函数

    将基类中的虚函数定义为public,在派生类中将该虚函数定义为private,则可以通过基类指针调用派生类的private函数 #include <iostream> #include & ...

  2. Cilium使用 (Cilium 3)

    使用k3s测试Cilium,安装步骤可以参见官方文档 Cilium安装使用 docker安装 使用如下命令安装最新版本的docker yum install -y yum-utils \ device ...

  3. Python变量详解

    Python变量详解 目录 Python变量详解 一.变量的定义 二.变量组成的三部分 2.1 变量名 2.1.1 变量名的命名规范 2.1.2 变量名的命名风格 2.2 赋值符号 2.3 变量值 三 ...

  4. 二分例题 51nod

    例题1 1010 只包含因子2 3 5的数 http://www.51nod.com/Challenge/Problem.html#problemId=1010 K的因子中只包含2 3 5.满足条件的 ...

  5. linux之cat 操作

    1.查看或创建 cat 1.txt #如果目录有这个文件则会打开查看,没有则会创建 2.压缩空白 cat 1.txt 我是第一行 我是第二 行 cat -bs 1.txt # 变成 cat 1.txt ...

  6. 从零开始学AB测试:躲坑篇

    AB测试的原理很简单,只用到了最简单的统计假设检验,但表面的简单通常都隐藏着陷阱,这一点没有经过实践的摸爬滚打是不容易看到的,今天我就把前人已经踩过的坑,一共15个,给大家分享一下.在分享之前,大家脑 ...

  7. 异常处理方式一(try-catch-finally)

    package com.yhqtv.demo01Exception; /* * 一.异常的处理,抓抛模型 * * 过程一:“抛”:程序在正常 执行的过程中,一旦出现异常,就会在异常代码处生成一个对应异 ...

  8. 第十二章Linux文件系统与日志

    1.inode 包含文件的元信息(1)inode 内容:文件的字节数.拥有者的 UID.GID.文件的读写执行权限.时间戳等,但不包含文件名.文件名是储存在目录的目录项中.(2)查看文件的 inode ...

  9. js 实现淘宝放大镜功能,可更改配置参数 带完整版解析代码[magnifier.js]

    前言:         本人纯小白一个,有很多地方理解的没有各位大牛那么透彻,如有错误,请各位大牛指出斧正!小弟感激不尽.         本篇文章为您分析一下原生JS写淘宝放大镜效果 基本功能: 运 ...

  10. 最大比例 公约数复用 【蓝桥真题】 (c++)

    最大比例 X星球的某个大奖赛设了M级奖励.每个级别的奖金是一个正整数.并且,相邻的两个级别间的比例是个固定值.也就是说:所有级别的奖金数构成了一个等比数列.比如:16,24,36,54其等比值为:3/ ...