发现最近碰到好多次二分结果的题目,上次多校也是,被我很机智的快速过了,这个思想确实非常不错。在正面求比较难处理的时候,二分结果再判断是否有效往往柳暗花明。

这个题目给定n个数字的序列,可以操作m次,每次要操作w个连续的数字,每次的操作将使得该段连续数字的数都+1,最后求整个序列最小值的最大值

求最小值最大,明显的二分结果的题目,我一开始还是在ACdream那个群里看到这个题,说是二分+线段树的题目,我就来做了一下。。首先二分部分很容易,下界就是初始序列的最小值,上界就是 下界+m,至于怎么判断这个就要想一下,我一开始还觉得不用线段树,因为我每次枚举完结果,对整个序列扫一遍,对不符合要求的数+到正好符号要求不就行了。

不过这个里面因为是要+连续一段,你普通的找到一个不符合条件的数,然后对他以及他之后的w-1个数都进行一次加法,很耗时啊,所以这个就是为什么要用线段树,其实我觉得用扫描线估计也可以,对某个起始点设置+1,起始点+w-1设置为-1,然后用个东西维护,++--的,估计也可以。反正最后用的线段树,普通的区间增,单点查询。

一开始还担心复杂度,不过还行的感觉,每次二分都要重新建树,这里就是 logN*N*logN,对二分结果进行判断,需要单点查询以及区间更新,这里是2*logN*logN,所以总的就是

logN*logN*(N+2)的复杂度,N最大为10的五次方,logN不超过20

#include <iostream>
#include <cstdio>
#include <cstring>
#define lson rt<<1,l,mid
#define rson rt<<1|1,mid+1,r
#define LL __int64
using namespace std;
const int N = 100000+10;
int n,m,w;
LL d[N<<2],flag[N<<2],A[N];
LL mini;
void up(int rt)
{
d[rt]=min(d[rt<<1],d[rt<<1|1]);
}
void build(int rt,int l,int r)
{
flag[rt]=0;
if (l>=r){
d[rt]=A[l];
//cout<<l<<" "<<A[l]<<endl;
return;
}
int mid=(l+r)>>1;
build(lson);
build(rson);
up(rt);
}
void pushdown(int rt,int l,int r)
{
if (flag[rt]==0) return;
d[rt<<1]+=flag[rt];
d[rt<<1|1]+=flag[rt];
flag[rt<<1]+=flag[rt];
flag[rt<<1|1]+=flag[rt];
flag[rt]=0;
}
LL query(int loc,int rt,int l,int r)
{
if (l==r) return d[rt];
int mid=(l+r)>>1;
pushdown(rt,l,r);
if (loc<=mid) return query(loc,lson);
else return query(loc,rson);
}
void update(LL val,int L,int R,int rt,int l,int r)
{
if (L<=l && r<=R){
d[rt]+=val;
flag[rt]+=val;
return;
}
pushdown(rt,l,r);
int mid=(l+r)>>1;
if (L<=mid) update(val,L,R,lson);
if (R>mid) update(val,L,R,rson);
up(rt);
}
bool judge(LL x)
{
LL tmp=m;
for (int i=1;i<=n;i++){
LL now=query(i,1,1,n);
// cout<<"Test "<<i<<endl;
// cout<<now<<endl;
if (now<x){
if (x-now>tmp) return 0;
else {
update(x-now,i,min(i+w-1,n),1,1,n);
tmp-=x-now;
}
}
}
return 1;
}
int main()
{
while (scanf("%d%d%d",&n,&m,&w)!=EOF)
{
mini=-1;
for (int i=1;i<=n;i++){
scanf("%I64d",&A[i]);
//cout<<i<<" "<<A[i]<<endl;
if (mini==-1) mini=A[i];
else mini=min(A[i],mini);
}
LL L=mini,R=mini+(LL)m,mid;
while (L<R){
build(1,1,n);
mid=R-(R-L)/2;
// cout<<L<<" "<<mid<<" "<<R<<endl;
if (judge(mid)) {L=mid;}
else {R=mid-1;}
}
printf("%I64d\n",L);
}
return 0; }

  

Codeforces 460C 二分结果+线段树维护的更多相关文章

  1. Codeforces 1136E(转化+线段树维护)

    题目传送 虽然线段树比较显然但是发现a数组并不好维护.考虑将a转化为好维护的数组b. 方法 这里我将k[1]设为0,对应着\[a[1] + k[1] <= a[2]\]不难得出\[a[i] + ...

  2. Codeforces 1093G题解(线段树维护k维空间最大曼哈顿距离)

    题意是,给出n个k维空间下的点,然后q次操作,每次操作要么修改其中一个点的坐标,要么查询下标为[l,r]区间中所有点中两点的最大曼哈顿距离. 思路:参考blog:https://blog.csdn.n ...

  3. Codeforces 777E Hanoi Factory(线段树维护DP)

    题目链接 Hanoi Factory 很容易想到这是一个DAG模型,那么状态转移方程就出来了. 但是排序的时候有个小细节:b相同时看a的值. 因为按照惯例,堆塔的时候肯定是内半径大的在下面. 因为N有 ...

  4. Codeforces GYM 100114 D. Selection 线段树维护DP

    D. Selection Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/gym/100114 Descriptio ...

  5. Codeforces Round #271 (Div. 2) E题 Pillars(线段树维护DP)

    题目地址:http://codeforces.com/contest/474/problem/E 第一次遇到这样的用线段树来维护DP的题目.ASC中也遇到过,当时也非常自然的想到了线段树维护DP,可是 ...

  6. Codeforces 834D The Bakery【dp+线段树维护+lazy】

    D. The Bakery time limit per test:2.5 seconds memory limit per test:256 megabytes input:standard inp ...

  7. [Codeforces]817F. MEX Queries 离散化+线段树维护

    [Codeforces]817F. MEX Queries You are given a set of integer numbers, initially it is empty. You sho ...

  8. codeforces Good bye 2016 E 线段树维护dp区间合并

    codeforces Good bye 2016 E 线段树维护dp区间合并 题目大意:给你一个字符串,范围为‘0’~'9',定义一个ugly的串,即串中的子串不能有2016,但是一定要有2017,问 ...

  9. Codeforces Round #343 (Div. 2) D. Babaei and Birthday Cake 线段树维护dp

    D. Babaei and Birthday Cake 题目连接: http://www.codeforces.com/contest/629/problem/D Description As you ...

随机推荐

  1. D. Cow and Snacks 并查集

    D. Cow and Snacks 题意:有n种小吃,m个人,每个人有两种喜欢的小吃,当一个人遇到两种自己都喜欢的小吃,可以都吃掉,问在最优的吃小吃顺序下,不能吃到自己喜欢的小吃的人数最少是多少? 题 ...

  2. 3676: [Apio2014]回文串 求回文串长度与出现次数的最大值

    「BZOJ3676」[Apio2014] 回文串   Description 考虑一个只包含小写拉丁字母的字符串s.我们定义s的一个子串t的“出 现值”为t在s中的出现次数乘以t的长度.请你求出s的所 ...

  3. 【剑指Offer面试编程题】题目1505:两个链表的第一个公共结点--九度OJ

    题目描述: 输入两个链表,找出它们的第一个公共结点. 输入: 输入可能包含多个测试样例. 对于每个测试案例,输入的第一行为两个整数m和n(1<=m,n<=1000):代表将要输入的两个链表 ...

  4. 题解 LG P2264

    这是题解P2264 先讲一下Trie,其实Trie也名前缀树,就是说:如果Trie中某串是某串的前缀,那么我们可以共用这个串也就是这样: 插入h.hk.jc,jcfa 那么,h节点会给h和hk共用,j ...

  5. 「Luogu1231」教辅的组成

    传送门 Luogu 解题思路 看到种匹配问题,马上想到最大流所以这就是一道SB题. 但是有一个小问题,就是每一本书都只能匹配一次,那么我们对所有书进行拆点即可,这个操作类似于这题 细节注意事项 细节有 ...

  6. python3列表操作

    1.Python列表脚本操作符 2.Python列表截取 切片的公式:[start : end : step] 1)切片的取值: list1 = [1, 4, 9, 16, 25] print(lis ...

  7. FieldByName().AsFloat只可以保留四位小数,四位以上应使用Value

    FieldByName('a').AsFloat to FieldByName('a').Value

  8. Java中很少用的CopyOnWriteArrayList

    类注释 /** * A thread-safe variant of {@link java.util.ArrayList} in which all mutative * operations ({ ...

  9. sklearn中的多项式回归算法

    sklearn中的多项式回归算法 1.多项式回归法多项式回归的思路和线性回归的思路以及优化算法是一致的,它是在线性回归的基础上在原来的数据集维度特征上增加一些另外的多项式特征,使得原始数据集的维度增加 ...

  10. L2-002. 链表去重(模拟)

    题意: 给定一个带整数键值的单链表L,本题要求你编写程序,删除那些键值的绝对值有重复的结点.即对任意键值K,只有键值或其绝对值等于K的第一个结点可以被保留.同时,所有被删除的结点必须被保存在另外一个链 ...