• CF1358E Are You Fired? 分类讨论


    题目:

    给你一个$n$和一个长度为$n$的序列。

    对于序列的前$lceilfrac{n}{2} ceil$项,第$i$项的值为$a_i$,对于序列的后面所有项,值均为$x$。

    你需要给出一个$k$,使得任意一个长度为$k$的子区间的和都$>0$,若有多解,输出任意一个,如果不存在这样的$k$,输出$-1$。

    直接给出结论:当$xgeq0$是,选出整段是最优的,直接检验长度为$n$的区间是否可行。

    而对于$x<0$的情况,答案的区间长度一定大于后$n-lceilfrac{n}{2} ceil$项。

    设$temp$为当前从大到小枚举到的区间长度,可以用线段树维护区间和最小值。

    当前区间个数为$n-temp+1$:

      如果这些区间和最小值$>0$,就找到了一个满足要求的区间长度;

      反之,区间长度$++$,满足区间长度的区间个数$--$,去掉最末尾的一个区间。

    #include <bits/stdc++.h>
    using namespace std;
    inline int read() {
    	int x=0,f=1;
    	char ch=getchar();
    	while(ch<'0'||ch>'9') {if(ch=='-') f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9') {x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	return x*f;
    }
    typedef long long ll;
    const int maxn=5e5+5;
    int n,a[maxn],x;
    ll sum[maxn],b[maxn];
    struct Node{
    	ll Min,lazy;
    }tree[maxn<<2];
    void pushup(int rt) {
    	tree[rt].Min=min(tree[rt<<1].Min,tree[rt<<1|1].Min);
    }
    void build(int rt,int l,int r) {
    	if(l==r) {
    		tree[rt].Min=b[l];
    		return;
    	}
    	int mid=l+r>>1;
    	build(rt<<1,l,mid);
    	build(rt<<1|1,mid+1,r);
    	pushup(rt);
    }
    void pushdown(int rt) {
    	if(tree[rt].lazy) {
    		ll x=tree[rt].lazy;tree[rt].lazy=0;
    		tree[rt<<1].Min+=x,tree[rt<<1|1].Min+=x;
    		tree[rt<<1].lazy+=x,tree[rt<<1|1].lazy+=x;
    	}
    }
    void update(int rt,int l,int r,int L,int R,ll x) {
    	if(L>R) return;
    	if(L<=l&&R>=r) {
    		tree[rt].Min+=x;
    		tree[rt].lazy+=x;
    		return;
    	}
    	pushdown(rt);
    	int mid=l+r>>1;
    	if(L<=mid) update(rt<<1,l,mid,L,R,x);
    	if(R>mid) update(rt<<1|1,mid+1,r,L,R,x);
    	pushup(rt);
    }
    ll query(int rt,int l,int r,int L,int R) {
    	if(L<=l&&R>=r) return tree[rt].Min;
    	pushdown(rt);
    	int mid=l+r>>1;
    	ll res=1e18;
    	if(L<=mid) res=query(rt<<1,l,mid,L,R);
    	if(R>mid) res=min(res,query(rt<<1|1,mid+1,r,L,R));
    	pushup(rt);
    	return res;
    }
    int main() {
    	n=read();
    	for(int i=1;i<=(n+1)/2;++i) a[i]=read();
    	x=read();
    	for(int i=(n+1)/2+1;i<=n;++i) a[i]=x;
    	for(int i=1;i<=n;++i) sum[i]=sum[i-1]+a[i];
    	if(x>=0) {
    		if(sum[n]>0) printf("%d
    ",n);
    		else puts("-1");
    	}
    	else {
    		int len=n-(n+1)/2+1;n=(n+1)/2;
    		for(int i=1;i<=n;++i) b[i]=sum[i+len-1]-sum[i-1];
    		build(1,1,n);
    		int temp=n;
    		while(temp) {
    			if(query(1,1,n,1,temp)<=0) {
    				temp--,len++;
    				update(1,1,n,1,temp,x);
    			}
    			else printf("%d
    ",len),exit(0);
    		}
    		puts("-1");
    	}
    	return 0;
    }
    
  • 相关阅读:
    11 并发编程-(线程)-信号量&Event&定时器
    10 并发编程-(线程)-GIL全局解释器锁&死锁与递归锁
    星级评定
    maven课程 项目管理利器-maven 3-5 maven生命周期和插件 4星
    maven课程 项目管理利器-maven 3-4 eclipse安装maven插件和新建maven项目
    maven课程 项目管理利器-maven 3-3 maven中的坐标和仓库
    maven课程 项目管理利器-maven 3-2 maven自动建立目录骨架
    maven课程 项目管理利器-maven 3-1 maven常用的构建命令
    maven课程 项目管理利器-maven 2-2第一个maven案例hellomaven
    maven课程 项目管理利器-maven 1-2maven介绍和环境搭建
  • 原文地址:https://www.cnblogs.com/1999-09-21Karry-erfs/p/14281422.html
Copyright © 2020-2023  润新知