我是靠谱客的博主 虚拟钢铁侠,最近开发中收集的这篇文章主要介绍Blog Post Rating CodeForces - 806E (线段树二分),觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

题目链接

 

题目大意: 有一个博客, 初始分数为$0$, 有$n$个人, 第$i$个人有一个期望值$a_i$,

如果第$i$个人浏览博客时,博客赞数高于$a_i$博客分数$-1$, 低于$+1$, 相等不变,

对于每个$i$, 求出$[1,i]$的人按任意顺序浏览博客后最大分数.

 

 

题解:

首先, 用贪心可以知道所有人按期望升序排列, 最后得分一定最大

由于期望有负数, 博客分数一定是先减后增的, 然后对这两段分类讨论

对于递减的段, 最后分数为递增递减的临界值

假设临界值为$x$, 设比$x$小的数的个数为$cnt_x$

可以发现$x$是第一个满足 $cnt_x+x>=0$ 的$x$

比方说排序后序列为$-10,-10,-10,-6,-2,-1$ 那么$x$就为$-4$

权值线段树上二分即可求出$x$ (初值设为$x$, 转为二分第一个$>=0$的数)

在考虑递增区间, 假设当前一共有$r$个数

有转移方程 $f_i=min(a_i,f_{i-1}+1),$ $f$为得分, $a$为排序后数组

可以得到$f_r=min(a_r,a_{r-1}+1,a_{r-2}+2,...,a_{l}+r-l,x+(r-x))$, $a_{l}$为第一个比$x$大的数

用权值线段树维护最小值即可 

 

 

 1 #include <iostream>
 2 #include <algorithm>
 3 #include <cstdio>
 4 #define REP(i,a,n) for(int i=a;i<=n;++i)
 5 #define mid ((l+r)>>1)
 6 #define lc (o<<1)
 7 #define rc (lc|1)
 8 #define ls lc,l,mid
 9 #define rs rc,mid+1,r
10 using namespace std;
11 
12 const int N = 5e5+10, INF = 0x3f3f3f3f;
13 
14 int n, m, ans;
15 struct _ {
16     int mx,tag;
17     void upd(int x) {
18         mx+=x,tag+=x;
19     }
20 } v1[N<<2], v2[N<<3];
21 
22 //v1维护的递减区间
23 //v2维护递增区间 
24 
25 void pd(_ *v, int o) {
26     if (v[o].tag) {
27         v[lc].upd(v[o].tag);
28         v[rc].upd(v[o].tag);
29         v[o].tag=0;
30     }
31 }
32 
33 void add1(int o, int l, int r, int ql, int qr) {
34     if (ql<=l&&r<=qr) return v1[o].upd(1);
35     pd(v1,o);
36     if (mid>=ql) add1(ls,ql,qr);
37     if (mid<qr) add1(rs,ql,qr);
38     v1[o].mx=max(v1[lc].mx,v1[rc].mx);
39 }
40 
41 void add2(int o, int l, int r, int ql, int qr) {
42     if (ql<=l&&r<=qr) return v2[o].upd(1);
43     pd(v2,o);
44     if (mid>=ql) add2(ls,ql,qr);
45     if (mid<qr) add2(rs,ql,qr);
46     v2[o].mx=min(v2[lc].mx,v2[rc].mx);
47 }
48 
49 int qry1(int o, int l, int r) {
50     if (l==r) return l;
51     pd(v1,o);
52     if (v1[lc].mx>=0) return qry1(ls);
53     return qry1(rs);
54 }
55 
56 void qry2(int o, int l, int r, int ql, int qr) {
57     if (v2[o].mx>=ans) return; 
58     if (ql<=l&&r<=qr) return ans=min(ans,v2[o].mx),void();
59     pd(v2,o);
60     if (mid>=ql) qry2(ls,ql,qr);
61     if (mid<qr) qry2(rs,ql,qr);
62 }
63 
64 void build1(int o, int l, int r) {
65     if (l==r) return v1[o].mx=l,void();
66     build1(ls),build1(rs);
67     v1[o].mx=max(v1[lc].mx,v1[rc].mx);
68 }
69 
70 void build2(int o, int l, int r) {
71     if (l==r) return v2[o].mx=l,void();
72     build2(ls),build2(rs);
73     v2[o].mx=min(v2[lc].mx,v2[rc].mx);
74 }
75 
76 int main() {
77     scanf("%d", &n);
78     build1(1,-N,0);
79     build2(1,-N,N);
80     REP(i,1,n) {
81         int k;
82         scanf("%d", &k);
83         if (k<0) add1(1,-N,0,k,N);
84         add2(1,-N,N,-N,k-1);
85         int x = qry1(1,-N,0);
86         ans = INF, qry2(1,-N,N,x,N);
87         printf("%dn", ans);
88     }
89 }

 

转载于:https://www.cnblogs.com/uid001/p/10248923.html

最后

以上就是虚拟钢铁侠为你收集整理的Blog Post Rating CodeForces - 806E (线段树二分)的全部内容,希望文章能够帮你解决Blog Post Rating CodeForces - 806E (线段树二分)所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(52)

评论列表共有 0 条评论

立即
投稿
返回
顶部